bool KRViewport::visible(const KRAABB &b) const { // test if bounding box would be within the visible range of the clip space transformed by matViewProjection // This is used for view frustrum culling int outside_count[6] = {0, 0, 0, 0, 0, 0}; for(int iCorner=0; iCorner<8; iCorner++) { KRVector4 sourceCornerVertex = KRVector4( (iCorner & 1) == 0 ? b.min.x : b.max.x, (iCorner & 2) == 0 ? b.min.y : b.max.y, (iCorner & 4) == 0 ? b.min.z : b.max.z, 1.0f); KRVector4 cornerVertex = KRMat4::Dot4(m_matViewProjection, sourceCornerVertex); if(cornerVertex.x < -cornerVertex.w) { outside_count[0]++; } if(cornerVertex.y < -cornerVertex.w) { outside_count[1]++; } if(cornerVertex.z < -cornerVertex.w) { outside_count[2]++; } if(cornerVertex.x > cornerVertex.w) { outside_count[3]++; } if(cornerVertex.y > cornerVertex.w) { outside_count[4]++; } if(cornerVertex.z > cornerVertex.w) { outside_count[5]++; } } bool is_visible = true; for(int iFace=0; iFace < 6; iFace++) { if(outside_count[iFace] == 8) { is_visible = false; } } return is_visible; }
bool KRShader::bind(KRCamera &camera, const KRViewport &viewport, const KRMat4 &matModel, const std::vector<KRPointLight *> &point_lights, const std::vector<KRDirectionalLight *> &directional_lights, const std::vector<KRSpotLight *>&spot_lights, const KRNode::RenderPass &renderPass, const KRVector3 &rim_color, float rim_power, const KRVector4 &fade_color) { if(m_iProgram == 0) { return false; } bool shander_changed = false; if(getContext().getShaderManager()->m_active_shader != this) { getContext().getShaderManager()->m_active_shader = this; GLDEBUG(glUseProgram(m_iProgram)); shander_changed = true; } setUniform(KRENGINE_UNIFORM_ABSOLUTE_TIME, getContext().getAbsoluteTime()); int light_directional_count = 0; int light_point_count = 0; int light_spot_count = 0; // TODO - Need to support multiple lights and more light types in forward rendering if(renderPass != KRNode::RENDER_PASS_DEFERRED_LIGHTS && renderPass != KRNode::RENDER_PASS_DEFERRED_GBUFFER && renderPass != KRNode::RENDER_PASS_DEFERRED_OPAQUE && renderPass != KRNode::RENDER_PASS_GENERATE_SHADOWMAPS) { for(std::vector<KRDirectionalLight *>::const_iterator light_itr=directional_lights.begin(); light_itr != directional_lights.end(); light_itr++) { KRDirectionalLight *directional_light = (*light_itr); if(light_directional_count == 0) { int cShadowBuffers = directional_light->getShadowBufferCount(); if(m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE1] != -1 && cShadowBuffers > 0) { if(m_pContext->getTextureManager()->selectTexture(GL_TEXTURE_2D, 3, directional_light->getShadowTextures()[0])) { GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); } m_pContext->getTextureManager()->_setWrapModeS(3, GL_CLAMP_TO_EDGE); m_pContext->getTextureManager()->_setWrapModeT(3, GL_CLAMP_TO_EDGE); } if(m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE2] != -1 && cShadowBuffers > 1 && camera.settings.m_cShadowBuffers > 1) { if(m_pContext->getTextureManager()->selectTexture(GL_TEXTURE_2D, 4, directional_light->getShadowTextures()[1])) { GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); } m_pContext->getTextureManager()->_setWrapModeS(4, GL_CLAMP_TO_EDGE); m_pContext->getTextureManager()->_setWrapModeT(4, GL_CLAMP_TO_EDGE); } if(m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE3] != -1 && cShadowBuffers > 2 && camera.settings.m_cShadowBuffers > 2) { if(m_pContext->getTextureManager()->selectTexture(GL_TEXTURE_2D, 5, directional_light->getShadowTextures()[2])) { GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); } m_pContext->getTextureManager()->_setWrapModeS(5, GL_CLAMP_TO_EDGE); m_pContext->getTextureManager()->_setWrapModeT(5, GL_CLAMP_TO_EDGE); } KRMat4 matBias; matBias.translate(1.0, 1.0, 1.0); matBias.scale(0.5); for(int iShadow=0; iShadow < cShadowBuffers; iShadow++) { setUniform(KRENGINE_UNIFORM_SHADOWMVP1 + iShadow, matModel * directional_light->getShadowViewports()[iShadow].getViewProjectionMatrix() * matBias); } if(m_uniforms[KRENGINE_UNIFORM_LIGHT_DIRECTION_MODEL_SPACE] != -1) { KRMat4 inverseModelMatrix = matModel; inverseModelMatrix.invert(); // Bind the light direction vector KRVector3 lightDirObject = KRMat4::Dot(inverseModelMatrix, directional_light->getWorldLightDirection()); lightDirObject.normalize(); setUniform(KRENGINE_UNIFORM_LIGHT_DIRECTION_MODEL_SPACE, lightDirObject); } } light_directional_count++; } light_point_count = point_lights.size(); light_spot_count = spot_lights.size(); } if(m_uniforms[KRENGINE_UNIFORM_CAMERAPOS_MODEL_SPACE] != -1) { KRMat4 inverseModelMatrix = matModel; inverseModelMatrix.invert(); if(m_uniforms[KRENGINE_UNIFORM_CAMERAPOS_MODEL_SPACE] != -1) { // Transform location of camera to object space for calculation of specular halfVec KRVector3 cameraPosObject = KRMat4::Dot(inverseModelMatrix, viewport.getCameraPosition()); setUniform(KRENGINE_UNIFORM_CAMERAPOS_MODEL_SPACE, cameraPosObject); } } if(m_uniforms[KRENGINE_UNIFORM_MVP] != -1 || m_uniforms[KRShader::KRENGINE_UNIFORM_INVMVP] != -1) { // Bind our modelmatrix variable to be a uniform called mvpmatrix in our shaderprogram KRMat4 mvpMatrix = matModel * viewport.getViewProjectionMatrix(); setUniform(KRENGINE_UNIFORM_MVP, mvpMatrix); if(m_uniforms[KRShader::KRENGINE_UNIFORM_INVMVP] != -1) { setUniform(KRShader::KRENGINE_UNIFORM_INVMVP, KRMat4::Invert(mvpMatrix)); } } if(m_uniforms[KRShader::KRENGINE_UNIFORM_VIEW_SPACE_MODEL_ORIGIN] != -1 || m_uniforms[KRENGINE_UNIFORM_MODEL_VIEW_INVERSE_TRANSPOSE] != -1 || m_uniforms[KRShader::KRENGINE_UNIFORM_MODEL_VIEW] != -1) { KRMat4 matModelView = matModel * viewport.getViewMatrix(); setUniform(KRENGINE_UNIFORM_MODEL_VIEW, matModelView); if(m_uniforms[KRShader::KRENGINE_UNIFORM_VIEW_SPACE_MODEL_ORIGIN] != -1) { KRVector3 view_space_model_origin = KRMat4::Dot(matModelView, KRVector3::Zero()); // Origin point of model space is the light source position. No perspective, so no w divide required setUniform(KRENGINE_UNIFORM_VIEW_SPACE_MODEL_ORIGIN, view_space_model_origin); } if(m_uniforms[KRENGINE_UNIFORM_MODEL_VIEW_INVERSE_TRANSPOSE] != -1) { KRMat4 matModelViewInverseTranspose = matModelView; matModelViewInverseTranspose.transpose(); matModelViewInverseTranspose.invert(); setUniform(KRENGINE_UNIFORM_MODEL_VIEW_INVERSE_TRANSPOSE, matModelViewInverseTranspose); } } if(m_uniforms[KRENGINE_UNIFORM_MODEL_INVERSE_TRANSPOSE] != -1) { KRMat4 matModelInverseTranspose = matModel; matModelInverseTranspose.transpose(); matModelInverseTranspose.invert(); setUniform(KRENGINE_UNIFORM_MODEL_INVERSE_TRANSPOSE, matModelInverseTranspose); } if(m_uniforms[KRShader::KRENGINE_UNIFORM_INVP] != -1) { setUniform(KRENGINE_UNIFORM_INVP, viewport.getInverseProjectionMatrix()); } if(m_uniforms[KRShader::KRENGINE_UNIFORM_INVMVP_NO_TRANSLATE] != -1) { KRMat4 matInvMVPNoTranslate = matModel * viewport.getViewMatrix();; // Remove the translation matInvMVPNoTranslate.getPointer()[3] = 0; matInvMVPNoTranslate.getPointer()[7] = 0; matInvMVPNoTranslate.getPointer()[11] = 0; matInvMVPNoTranslate.getPointer()[12] = 0; matInvMVPNoTranslate.getPointer()[13] = 0; matInvMVPNoTranslate.getPointer()[14] = 0; matInvMVPNoTranslate.getPointer()[15] = 1.0; matInvMVPNoTranslate = matInvMVPNoTranslate * viewport.getProjectionMatrix(); matInvMVPNoTranslate.invert(); setUniform(KRENGINE_UNIFORM_INVMVP_NO_TRANSLATE, matInvMVPNoTranslate); } setUniform(KRENGINE_UNIFORM_MODEL_MATRIX, matModel); if(m_uniforms[KRENGINE_UNIFORM_PROJECTION_MATRIX] != -1) { setUniform(KRENGINE_UNIFORM_PROJECTION_MATRIX, viewport.getProjectionMatrix()); } if(m_uniforms[KRENGINE_UNIFORM_VIEWPORT] != -1) { setUniform(KRENGINE_UNIFORM_VIEWPORT, KRVector4( (GLfloat)0.0, (GLfloat)0.0, (GLfloat)viewport.getSize().x, (GLfloat)viewport.getSize().y ) ); } if(m_uniforms[KRENGINE_UNIFORM_VIEWPORT_DOWNSAMPLE] != -1) { setUniform(KRENGINE_UNIFORM_VIEWPORT_DOWNSAMPLE, camera.getDownsample()); } // Rim highlighting parameters setUniform(KRENGINE_UNIFORM_RIM_COLOR, rim_color); setUniform(KRENGINE_UNIFORM_RIM_POWER, rim_power); // Fade parameters setUniform(KRENGINE_UNIFORM_FADE_COLOR, fade_color); // Fog parameters setUniform(KRENGINE_UNIFORM_FOG_NEAR, camera.settings.fog_near); setUniform(KRENGINE_UNIFORM_FOG_FAR, camera.settings.fog_far); setUniform(KRENGINE_UNIFORM_FOG_DENSITY, camera.settings.fog_density); setUniform(KRENGINE_UNIFORM_FOG_COLOR, camera.settings.fog_color); if(m_uniforms[KRENGINE_UNIFORM_FOG_SCALE] != -1) { setUniform(KRENGINE_UNIFORM_FOG_SCALE, 1.0f / (camera.settings.fog_far - camera.settings.fog_near)); } if(m_uniforms[KRENGINE_UNIFORM_DENSITY_PREMULTIPLIED_EXPONENTIAL] != -1) { setUniform(KRENGINE_UNIFORM_DENSITY_PREMULTIPLIED_EXPONENTIAL, -camera.settings.fog_density * 1.442695f); // -fog_density / log(2) } if(m_uniforms[KRENGINE_UNIFORM_DENSITY_PREMULTIPLIED_SQUARED] != -1) { setUniform(KRENGINE_UNIFORM_DENSITY_PREMULTIPLIED_SQUARED, (float)(-camera.settings.fog_density * camera.settings.fog_density * 1.442695)); // -fog_density * fog_density / log(2) } // Sets the diffuseTexture variable to the first texture unit setUniform(KRENGINE_UNIFORM_DIFFUSETEXTURE, 0); // Sets the specularTexture variable to the second texture unit setUniform(KRENGINE_UNIFORM_SPECULARTEXTURE, 1); // Sets the normalTexture variable to the third texture unit setUniform(KRENGINE_UNIFORM_NORMALTEXTURE, 2); // Sets the shadowTexture variable to the fourth texture unit setUniform(KRENGINE_UNIFORM_SHADOWTEXTURE1, 3); setUniform(KRENGINE_UNIFORM_SHADOWTEXTURE2, 4); setUniform(KRENGINE_UNIFORM_SHADOWTEXTURE3, 5); setUniform(KRENGINE_UNIFORM_REFLECTIONCUBETEXTURE, 4); setUniform(KRENGINE_UNIFORM_LIGHTMAPTEXTURE, 5); setUniform(KRENGINE_UNIFORM_GBUFFER_FRAME, 6); setUniform(KRENGINE_UNIFORM_GBUFFER_DEPTH, 7); // Texture unit 7 is used for reading the depth buffer in gBuffer pass #2 and in post-processing pass setUniform(KRENGINE_UNIFORM_REFLECTIONTEXTURE, 7); // Texture unit 7 is used for the reflection map textures in gBuffer pass #3 and when using forward rendering setUniform(KRENGINE_UNIFORM_DEPTH_FRAME, 0); setUniform(KRENGINE_UNIFORM_RENDER_FRAME, 1); setUniform(KRENGINE_UNIFORM_VOLUMETRIC_ENVIRONMENT_FRAME, 2); #if defined(DEBUG) if(shander_changed) { // FINDME!! KIP!! HACK!! GLint logLength; GLint validate_status = GL_FALSE; GLDEBUG(glValidateProgram(m_iProgram)); GLDEBUG(glGetProgramiv(m_iProgram, GL_VALIDATE_STATUS, &validate_status)); if(validate_status != GL_TRUE) { KRContext::Log(KRContext::LOG_LEVEL_ERROR, "KREngine - Failed to validate shader program: %s", m_szKey); GLDEBUG(glGetProgramiv(m_iProgram, GL_INFO_LOG_LENGTH, &logLength)); if (logLength > 0) { GLchar *log = (GLchar *)malloc(logLength + 1); assert(log != NULL); GLDEBUG(glGetProgramInfoLog(m_iProgram, logLength, &logLength, log)); log[logLength] = '\0'; KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Program validate log:\n%s", log); free(log); } return false; } } #endif return true; }