1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
#include "GeometryBuffer.h"
#include "Rendering/GlobalRendering.h"
#include <cstring> //memset
void GL::GeometryBuffer::Init() {
memset(&bufferTextureIDs[0], 0, sizeof(bufferTextureIDs));
memset(&bufferAttachments[0], 0, sizeof(bufferAttachments));
// NOTE:
// Lua can toggle drawDeferred and might be the
// first to call us --> initial buffer size must
// be (0, 0) so prevSize != currSize (when !init)
prevBufferSize = GetWantedSize(false);
currBufferSize = GetWantedSize(true);
}
void GL::GeometryBuffer::Kill() {
if (buffer.IsValid()) {
DetachTextures(false);
}
}
void GL::GeometryBuffer::DetachTextures(const bool init) {
if (init) {
// nothing to detach yet during init
return;
}
buffer.Bind();
// ATI drivers crash when detaching non-attached textures (?)
for (unsigned int i = 0; i < (ATTACHMENT_COUNT - 1); ++i) {
buffer.Detach(GL_COLOR_ATTACHMENT0_EXT + i);
}
buffer.Detach(GL_DEPTH_ATTACHMENT_EXT);
buffer.Unbind();
glDeleteTextures(ATTACHMENT_COUNT, &bufferTextureIDs[0]);
// return to incomplete state
memset(&bufferTextureIDs[0], 0, sizeof(bufferTextureIDs));
memset(&bufferAttachments[0], 0, sizeof(bufferAttachments));
}
void GL::GeometryBuffer::DrawDebug(unsigned int texID) {
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texID);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glNormal3f(0.0f, 1.0f, 0.0f); glVertex2f(0.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glNormal3f(0.0f, 1.0f, 0.0f); glVertex2f(1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glNormal3f(0.0f, 1.0f, 0.0f); glVertex2f(1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glNormal3f(0.0f, 1.0f, 0.0f); glVertex2f(0.0f, 1.0f);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
bool GL::GeometryBuffer::Create(const int2 size) {
buffer.Bind();
for (unsigned int n = 0; n < ATTACHMENT_COUNT; n++) {
glGenTextures(1, &bufferTextureIDs[n]);
glBindTexture(GL_TEXTURE_2D, bufferTextureIDs[n]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if (n == ATTACHMENT_ZVALTEX) {
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, size.x, size.y, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
bufferAttachments[n] = GL_DEPTH_ATTACHMENT_EXT;
} else {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.x, size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
bufferAttachments[n] = GL_COLOR_ATTACHMENT0_EXT + n;
}
buffer.AttachTexture(bufferTextureIDs[n], GL_TEXTURE_2D, bufferAttachments[n]);
}
glBindTexture(GL_TEXTURE_2D, 0);
// define the attachments we are going to draw into
// note: the depth-texture attachment does not count
// here and will be GL_NONE implicitly!
glDrawBuffers(ATTACHMENT_COUNT - 1, &bufferAttachments[0]);
// FBO must have been valid from point of construction
// if we reached CreateGeometryBuffer, but CheckStatus
// can still invalidate it
assert(buffer.IsValid());
const bool ret = buffer.CheckStatus(bufferName);
buffer.Unbind();
return ret;
}
bool GL::GeometryBuffer::Update(const bool init) {
currBufferSize = GetWantedSize(true);
// FBO must be valid from point of construction
if (!buffer.IsValid())
return false;
// buffer isn't bound by calling context, can not call
// GetStatus to check for GL_FRAMEBUFFER_COMPLETE_EXT
//
if (HasAttachments()) {
// technically a buffer can not be complete yet during
// initialization, however the GL spec says that FBO's
// with only empty attachments are complete by default
// assert(!init);
// FBO was already initialized (during init or from Lua)
// so it will have attachments -> check if they need to
// be regenerated, eg. if a window resize event happened
if (prevBufferSize == currBufferSize)
return true;
DetachTextures(init);
}
return (Create(prevBufferSize = currBufferSize));
}
int2 GL::GeometryBuffer::GetWantedSize(bool allowed) const {
if (allowed)
return (int2(globalRendering->viewSizeX, globalRendering->viewSizeY));
return (int2(0, 0));
}
|