Framebuffer::Framebuffer(int width, int height) : width(width), height(height), id(allocFramebuffer()), texId(allocTexture(width, height)) { SDL::glBindFramebuffer(GL_FRAMEBUFFER, id); SDL::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texId, 0); SDL::GLenum drawTargets[1] = {GL_COLOR_ATTACHMENT0}; SDL::glDrawBuffers(1, drawTargets); auto ret = SDL::glCheckFramebufferStatus(GL_FRAMEBUFFER); CHECK(ret == GL_FRAMEBUFFER_COMPLETE); unbind(); }
static int fboPrologue (CompScreen *s, int tIndex) { WATER_SCREEN (s); if (!ws->fbo) return 0; if (!ws->texture[tIndex]) allocTexture (s, tIndex); (*s->bindFramebuffer) (GL_FRAMEBUFFER_EXT, ws->fbo); (*s->framebufferTexture2D) (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, ws->target, ws->texture[tIndex], 0); glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT); glReadBuffer (GL_COLOR_ATTACHMENT0_EXT); /* check status the first time */ if (!ws->fboStatus) { ws->fboStatus = (*s->checkFramebufferStatus) (GL_FRAMEBUFFER_EXT); if (ws->fboStatus != GL_FRAMEBUFFER_COMPLETE_EXT) { compLogMessage ("water", CompLogLevelError, "framebuffer incomplete"); (*s->bindFramebuffer) (GL_FRAMEBUFFER_EXT, 0); (*s->deleteFramebuffers) (1, &ws->fbo); glDrawBuffer (GL_BACK); glReadBuffer (GL_BACK); ws->fbo = 0; return 0; } } glViewport (0, 0, ws->width, ws->height); glMatrixMode (GL_PROJECTION); glPushMatrix (); glLoadIdentity (); glOrtho (0.0, 1.0, 0.0, 1.0, -1.0, 1.0); glMatrixMode (GL_MODELVIEW); glPushMatrix (); glLoadIdentity (); return 1; }
static void softwareUpdate(CompScreen * s, float dt, float fade) { float *dTmp; int i, j; float v0, v1, inv; float accel, value; unsigned char *t0, *t; int dWidth, dHeight; float *d01, *d10, *d11, *d12; WATER_SCREEN(s); if (!ws->texture[TINDEX(ws, 0)]) allocTexture(s, TINDEX(ws, 0)); dt *= K * 2.0f; fade *= 0.99f; dWidth = ws->width + 2; dHeight = ws->height + 2; #define D(d, j) (*((d) + (j))) d01 = ws->d0 + dWidth; d10 = ws->d1; d11 = d10 + dWidth; d12 = d11 + dWidth; for (i = 1; i < dHeight - 1; i++) { for (j = 1; j < dWidth - 1; j++) { accel = dt * (D(d10, j) + D(d12, j) + D(d11, j - 1) + D(d11, j + 1) - 4.0f * D(d11, j)); value = (2.0f * D(d11, j) - D(d01, j) + accel) * fade; CLAMP(value, 0.0f, 1.0f); D(d01, j) = value; } d01 += dWidth; d10 += dWidth; d11 += dWidth; d12 += dWidth; } /* update border */ memcpy(ws->d0, ws->d0 + dWidth, dWidth * sizeof(GLfloat)); memcpy(ws->d0 + dWidth * (dHeight - 1), ws->d0 + dWidth * (dHeight - 2), dWidth * sizeof(GLfloat)); d01 = ws->d0 + dWidth; for (i = 1; i < dHeight - 1; i++) { D(d01, 0) = D(d01, 1); D(d01, dWidth - 1) = D(d01, dWidth - 2); d01 += dWidth; } d10 = ws->d1; d11 = d10 + dWidth; d12 = d11 + dWidth; t0 = ws->t0; /* update texture */ for (i = 0; i < ws->height; i++) { for (j = 0; j < ws->width; j++) { v0 = (D(d12, j) - D(d10, j)) * 1.5f; v1 = (D(d11, j - 1) - D(d11, j + 1)) * 1.5f; /* 0.5 for scale */ inv = 0.5f / sqrtf(v0 * v0 + v1 * v1 + 1.0f); /* add scale and bias to normal */ v0 = v0 * inv + 0.5f; v1 = v1 * inv + 0.5f; /* store normal map in RGB components */ t = t0 + (j * 4); t[0] = (unsigned char)((inv + 0.5f) * 255.0f); t[1] = (unsigned char)(v1 * 255.0f); t[2] = (unsigned char)(v0 * 255.0f); /* store height in A component */ t[3] = (unsigned char)(D(d11, j) * 255.0f); } d10 += dWidth; d11 += dWidth; d12 += dWidth; t0 += ws->width * 4; } #undef D /* swap height maps */ dTmp = ws->d0; ws->d0 = ws->d1; ws->d1 = dTmp; if (ws->texture[TINDEX(ws, 0)]) { glBindTexture(ws->target, ws->texture[TINDEX(ws, 0)]); glTexImage2D(ws->target, 0, GL_RGBA, ws->width, ws->height, 0, GL_BGRA, #if IMAGE_BYTE_ORDER == MSBFirst GL_UNSIGNED_INT_8_8_8_8_REV, #else GL_UNSIGNED_BYTE, #endif ws->t0); } }
static int fboUpdate(CompScreen * s, float dt, float fade) { WATER_SCREEN(s); if (!fboPrologue(s, TINDEX(ws, 1))) return 0; if (!ws->texture[TINDEX(ws, 2)]) allocTexture(s, TINDEX(ws, 2)); if (!ws->texture[TINDEX(ws, 0)]) allocTexture(s, TINDEX(ws, 0)); glEnable(ws->target); (*s->activeTexture) (GL_TEXTURE0_ARB); glBindTexture(ws->target, ws->texture[TINDEX(ws, 2)]); glTexParameteri(ws->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(ws->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); (*s->activeTexture) (GL_TEXTURE1_ARB); glBindTexture(ws->target, ws->texture[TINDEX(ws, 0)]); glTexParameteri(ws->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(ws->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glEnable(GL_FRAGMENT_PROGRAM_ARB); (*s->bindProgram) (GL_FRAGMENT_PROGRAM_ARB, ws->program); (*s->programLocalParameter4f) (GL_FRAGMENT_PROGRAM_ARB, 0, dt * K, fade, 1.0f, 1.0f); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex2f(0.0f, 0.0f); glTexCoord2f(ws->tx, 0.0f); glVertex2f(1.0f, 0.0f); glTexCoord2f(ws->tx, ws->ty); glVertex2f(1.0f, 1.0f); glTexCoord2f(0.0f, ws->ty); glVertex2f(0.0f, 1.0f); glEnd(); glDisable(GL_FRAGMENT_PROGRAM_ARB); glTexParameteri(ws->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(ws->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glBindTexture(ws->target, 0); (*s->activeTexture) (GL_TEXTURE0_ARB); glTexParameteri(ws->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(ws->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glBindTexture(ws->target, 0); glDisable(ws->target); fboEpilogue(s); /* increment texture index */ ws->tIndex = TINDEX(ws, 1); return 1; }