#include "client/engine/shader/WorldShader.h" #include "client/engine/Wrapper.h" WorldShader::WorldShader() { } WorldShader::~WorldShader() { glDeleteFramebuffers(1, &framebuffer); glDeleteTextures(1, &positionTexture); glDeleteTextures(1, &normalTexture); glDeleteTextures(1, &colorTexture); glDeleteTextures(1, &depthTexture); } bool WorldShader::init() { program.compile("resources/shader/worldVertex.vs", "resources/shader/worldFragment.fs"); if(!program.isValid()) { return false; } // generate framebuffer glGenFramebuffers(1, &framebuffer); glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); // position texture glGenTextures(1, &positionTexture); glBindTexture(GL_TEXTURE_2D, positionTexture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, Engine::getWidth(), Engine::getHeight(), 0, GL_RGB, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // attache position texture to framebuffer glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, positionTexture, 0); // normal texture glGenTextures(1, &normalTexture); glBindTexture(GL_TEXTURE_2D, normalTexture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, Engine::getWidth(), Engine::getHeight(), 0, GL_RGB, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // attache normal texture to framebuffer glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, normalTexture, 0); // color texture glGenTextures(1, &colorTexture); glBindTexture(GL_TEXTURE_2D, colorTexture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Engine::getWidth(), Engine::getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // attache color texture to framebuffer glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, colorTexture, 0); // depth texture glGenTextures(1, &depthTexture); glBindTexture(GL_TEXTURE_2D, depthTexture); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, Engine::getWidth(), Engine::getHeight(), 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // attache depth texture to framebuffer glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0); // set color attachements for the framebuffer GLuint attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 }; glDrawBuffers(3, attachments); // check if framebuffer is okay if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { cout << "world frame buffer is not complete!" << endl; return false; } // unbind framebuffer glBindFramebuffer(GL_FRAMEBUFFER, 0); // get uniform locations unifProjMatrix = glGetUniformLocation(program.getProgram(), "projMatrix"); unifViewMatrix = glGetUniformLocation(program.getProgram(), "viewMatrix"); unifModelMatrix = glGetUniformLocation(program.getProgram(), "modelMatrix"); return true; } void WorldShader::resize() { glBindTexture(GL_TEXTURE_2D, positionTexture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, Engine::getWidth(), Engine::getHeight(), 0, GL_RGB, GL_FLOAT, NULL); glBindTexture(GL_TEXTURE_2D, normalTexture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, Engine::getWidth(), Engine::getHeight(), 0, GL_RGB, GL_FLOAT, NULL); glBindTexture(GL_TEXTURE_2D, colorTexture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Engine::getWidth(), Engine::getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glBindTexture(GL_TEXTURE_2D, depthTexture); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, Engine::getWidth(), Engine::getHeight(), 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL); } void WorldShader::preRender(const float* projMatrix) { // bind world shader program glUseProgram(program.getProgram()); // set projection matrix uniform glUniformMatrix4fv(unifProjMatrix, 1, 0, projMatrix); // all textures bind to texture unit 0 glActiveTexture(GL_TEXTURE0); // bind world framebuffer glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); // clear color, depth and stencil buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // depth testing is needed glEnable(GL_DEPTH_TEST); } void WorldShader::bindPositionTexture(unsigned int textureUnit) { glActiveTexture(GL_TEXTURE0 + textureUnit); glBindTexture(GL_TEXTURE_2D, positionTexture); } void WorldShader::bindNormalTexture(unsigned int textureUnit) { glActiveTexture(GL_TEXTURE0 + textureUnit); glBindTexture(GL_TEXTURE_2D, normalTexture); } void WorldShader::bindColorTexture(unsigned int textureUnit) { glActiveTexture(GL_TEXTURE0 + textureUnit); glBindTexture(GL_TEXTURE_2D, colorTexture); } void WorldShader::bindDepthTexture(unsigned int textureUnit) { glActiveTexture(GL_TEXTURE0 + textureUnit); glBindTexture(GL_TEXTURE_2D, depthTexture); } void WorldShader::setViewMatrix(const float* data) { glUniformMatrix4fv(unifViewMatrix, 1, 0, data); } void WorldShader::setModelMatrix(const float* data) { glUniformMatrix4fv(unifModelMatrix, 1, 0, data); }