//======================================================================== // Shaders.cpp - helper classes to call GameCode4_VS.hlsl and GameCode4_PS.hlsl // // Part of the GameCode4 Application // // GameCode4 is the sample application that encapsulates much of the source code // discussed in "Game Coding Complete - 4th Edition" by Mike McShaffry and David // "Rez" Graham, published by Charles River Media. // ISBN-10: 1133776574 | ISBN-13: 978-1133776574 // // If this source code has found it's way to you, and you think it has helped you // in any way, do the authors a favor and buy a new copy of the book - there are // detailed explanations in it that compliment this code well. Buy a copy at Amazon.com // by clicking here: // http://www.amazon.com/gp/product/1133776574/ref=olp_product_details?ie=UTF8&me=&seller= // // There's a companion web site at http://www.mcshaffry.com/GameCode/ // // The source code is managed and maintained through Google Code: // http://code.google.com/p/gamecode4/ // // (c) Copyright 2012 Michael L. McShaffry and David Graham // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser GPL v3 // as published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See // http://www.gnu.org/licenses/lgpl-3.0.txt for more details. // // You should have received a copy of the GNU Lesser GPL v3 // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // //======================================================================== #include "../Unix/GameCodeStd.h" #include "../GameCode4/GameCode.h" #include "Shaders.h" #include "OpenGLRenderer.h" #include "Geometry.h" #include "Lights.h" // #include "Mesh.h" #include "Scene.h" #include "SceneNodes.h" #include "../ResourceCache/ResCache.h" #include // #include // #pragma comment(lib, "effects11.lib") // [mrmike] Note you can remove this if you don't want the D3DX11CreateEffectFromMemory API. // #include "d3dx11effect.h" OpenGLShader::OpenGLShader() : m_shaderId(0) { } OpenGLShader::~OpenGLShader() { } OpenGLShaderProgram::OpenGLShaderProgram() : m_enableLights(true), m_programId(0), m_textureResource("") { } OpenGLShaderProgram::~OpenGLShaderProgram() { glDeleteProgram(m_programId); } int OpenGLShaderProgram::OnRestore(Scene *pScene) { GLuint vShaderId; GLuint fShaderId; glDeleteBuffers(1, &m_matrixUbo); glDeleteBuffers(1, &m_lightsUbo); glDeleteBuffers(1, &m_materialsUbo); glDeleteProgram(m_programId); // in case we have an existing program that we need to get rid of m_programId = glCreateProgram(); { std::string vertFileName = "Effects/GameCode4_vert.glsl"; Resource resource(vertFileName.c_str()); std::shared_ptr pResourceHandle = g_pApp->m_ResCache->GetHandle(&resource); GLint status; vShaderId = glCreateShader(GL_VERTEX_SHADER); const GLchar *source = pResourceHandle->Buffer(); glShaderSource(vShaderId, 1, &source, NULL); glCompileShader(vShaderId); glGetShaderiv(vShaderId, GL_COMPILE_STATUS, &status); if (status == GL_FALSE) { GLint lsize = 0; glGetShaderiv(vShaderId, GL_INFO_LOG_LENGTH, &lsize); GLchar *log = new GLchar[lsize]; glGetShaderInfoLog(vShaderId, lsize, nullptr, log); GCC_ERROR(source); GCC_ERROR(log); delete[] log; return 1; } glAttachShader(m_programId, vShaderId); } { std::string fragFileName = "Effects/GameCode4_frag.glsl"; Resource resource(fragFileName.c_str()); std::shared_ptr pResourceHandle = g_pApp->m_ResCache->GetHandle(&resource); GLint status; fShaderId = glCreateShader(GL_FRAGMENT_SHADER); const GLchar *source = pResourceHandle->Buffer(); glShaderSource(fShaderId, 1, &source, NULL); glCompileShader(fShaderId); glGetShaderiv(fShaderId, GL_COMPILE_STATUS, &status); if (status == GL_FALSE) { GLint lsize = 0; glGetShaderiv(fShaderId, GL_INFO_LOG_LENGTH, &lsize); GLchar *log = new GLchar[lsize]; glGetShaderInfoLog(fShaderId, lsize, nullptr, log); GCC_ERROR(source); GCC_ERROR(log); delete[] log; return 1; } glAttachShader(m_programId, fShaderId); } glLinkProgram(m_programId); glDetachShader(m_programId, vShaderId); glDeleteShader(vShaderId); glDetachShader(m_programId, fShaderId); glDeleteShader(fShaderId); glGenBuffers(1, &m_matrixUbo); glBindBuffer(GL_UNIFORM_BUFFER, m_matrixUbo); glBufferStorage(GL_UNIFORM_BUFFER, sizeof(ConstantBuffer_Matrices), nullptr, GL_MAP_WRITE_BIT | GL_DYNAMIC_STORAGE_BIT); glGenBuffers(1, &m_lightsUbo); glBindBuffer(GL_UNIFORM_BUFFER, m_lightsUbo); glBufferStorage(GL_UNIFORM_BUFFER, sizeof(ConstantBuffer_Lighting), nullptr, GL_MAP_WRITE_BIT | GL_DYNAMIC_STORAGE_BIT); glGenBuffers(1, &m_materialsUbo); glBindBuffer(GL_UNIFORM_BUFFER, m_materialsUbo); glBufferStorage(GL_UNIFORM_BUFFER, sizeof(ConstantBuffer_Material), nullptr, GL_MAP_WRITE_BIT | GL_DYNAMIC_STORAGE_BIT); return 0; } int OpenGLShaderProgram::SetupRender(Scene *pScene, SceneNode *pNode) { glUseProgram(m_programId); // Get the projection & view matrix from the camera class glm::mat4 mWorldViewProjection = pScene->GetCamera()->GetWorldViewProjection(pScene); glm::mat4 mWorld = pScene->GetTopMatrix(); // ----- Transform Matricies ------ glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_matrixUbo); ConstantBuffer_Matrices* pVSMatrices = (ConstantBuffer_Matrices*)glMapBufferRange(GL_UNIFORM_BUFFER, 0, sizeof(ConstantBuffer_Matrices), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); pVSMatrices->m_WorldViewProj = mWorldViewProjection; pVSMatrices->m_World = mWorld; glUnmapBuffer(GL_UNIFORM_BUFFER); // ----- Lighting ------ glBindBufferBase(GL_UNIFORM_BUFFER, 1, m_lightsUbo); ConstantBuffer_Lighting* pLighting = (ConstantBuffer_Lighting*)glMapBufferRange(GL_UNIFORM_BUFFER, 0, sizeof(ConstantBuffer_Lighting), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); if (m_enableLights) { pScene->GetLightManager()->CalcLighting(pLighting, pNode); } else { pLighting->m_nNumLights = 0; pLighting->m_vLightAmbient = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f); } glUnmapBuffer(GL_UNIFORM_BUFFER); // ----- Material ------ glBindBufferBase(GL_UNIFORM_BUFFER, 2, m_materialsUbo); ConstantBuffer_Material* pPSMaterial = ( ConstantBuffer_Material* )glMapBufferRange(GL_UNIFORM_BUFFER, 0, sizeof(ConstantBuffer_Material), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); Color color = pNode->VGet()->GetMaterial().GetDiffuse(); pPSMaterial->m_vDiffuseObjectColor = glm::vec4(color.r, color.g, color.b, color.a); color = (m_enableLights) ? pNode->VGet()->GetMaterial().GetAmbient() : Color(1.0f, 1.0f, 1.0f, 1.0f); pPSMaterial->m_vAmbientObjectColor = glm::vec4(color.r, color.g, color.b, color.a); // Note - the vertex shader doesn't care about the texture one way or another so we'll just set it to false if (m_textureResource.length() > 0) { pPSMaterial->m_bHasTexture = true; } else { pPSMaterial->m_bHasTexture = false; } glUnmapBuffer(GL_UNIFORM_BUFFER); // Set up the texture SetTexture(m_textureResource); return 0; } int OpenGLShaderProgram::SetTexture(const std::string& textureName) { m_textureResource = textureName; if (m_textureResource.length() > 0) { Resource resource(m_textureResource); std::shared_ptr texture = g_pApp->m_ResCache->GetHandle(&resource); if (texture) { std::shared_ptr extra = static_pointer_cast(texture->GetExtra()); glBindTexture(GL_TEXTURE_2D, extra->GetTextureId()); } } }