Hello, I’m new to this forum and I’d like to receive some help, but I’m quite stupid, so try and bear with me here, ok?
I’m trying to use some tutorial to learn OpenGL, it’s on some arcsynthesis site and YES a lot of people told me that it’s got a difficult learning curve, but I got so far in that I don’t want to start over now!
So I’d want to create some scene, for fun and all, and the closest I got to it so far was tutorial 7 from their site. There I mostly play with “World with UBO”
ColorMultiUniform.frag:
#version 330
smooth in vec4 interpColor;
uniform vec4 baseColor;out vec4 outputColor;
void main()
{
outputColor = interpColor * baseColor;
}
ColorPassthrough.frag:
#version 330
smooth in vec4 interpColor;
out vec4 outputColor;
void main()
{
outputColor = interpColor;
}
ColorUniform.frag:
#version 330
uniform vec4 baseColor;
out vec4 outputColor;
void main()
{
outputColor = baseColor;
}
PosColorWorldTransformUbo.vert:
#version 330
layout(location = 0) in vec4 position;
layout(location = 1) in vec4 color;smooth out vec4 interpColor;
layout(std140) uniform GlobalMatrices
{
mat4 cameraToClipMatrix;
mat4 worldToCameraMatrix;
};uniform mat4 modelToWorldMatrix;
void main()
{
vec4 temp = modelToWorldMatrix * position;
temp = worldToCameraMatrix * temp;
gl_Position = cameraToClipMatrix * temp;
interpColor = color;
}
PosOnlyWorldTransformUbo.vert:
#version 330
layout(location = 0) in vec4 position;
layout(std140) uniform GlobalMatrices
{
mat4 cameraToClipMatrix;
mat4 worldToCameraMatrix;
};uniform mat4 modelToWorldMatrix;
void main()
{
vec4 temp = modelToWorldMatrix * position;
temp = worldToCameraMatrix * temp;
gl_Position = cameraToClipMatrix * temp;
}
And finally, World With Ubo.cpp:
//Copyright (C) 2010-2012 by Jason L. McKesson
//This file is licensed under the MIT License.#include <string>
#include <vector>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <glload/gl_3_3.h>
#include <glutil/glutil.h>
#include <GL/freeglut.h>
#include “…/framework/framework.h”
#include “…/framework/Mesh.h”
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>#define ARRAY_COUNT( array ) (sizeof( array ) / (sizeof( array[0] ) * (sizeof( array ) != sizeof(void*) || sizeof( array[0] ) <= sizeof(void*))))
struct ProgramData
{
GLuint theProgram;
GLuint globalUniformBlockIndex;
GLuint modelToWorldMatrixUnif;
GLuint baseColorUnif;
GLuint thing;
};float g_fzNear = 1.0f;
float g_fzFar = 1000.0f;ProgramData UniformColor;
ProgramData ObjectColor;
ProgramData UniformColorTint;GLuint g_GlobalMatricesUBO;
static const int g_iGlobalMatricesBindingIndex = 0;
ProgramData LoadProgram(const std::string &strVertexShader, const std::string &strFragmentShader)
{
std::vector<GLuint> shaderList;shaderList.push_back(Framework::LoadShader(GL_VERTEX_SHADER, strVertexShader));
shaderList.push_back(Framework::LoadShader(GL_FRAGMENT_SHADER, strFragmentShader));ProgramData data;
data.theProgram = Framework::CreateProgram(shaderList);
data.modelToWorldMatrixUnif = glGetUniformLocation(data.theProgram, “modelToWorldMatrix”);
data.globalUniformBlockIndex = glGetUniformBlockIndex(data.theProgram, “GlobalMatrices”);
data.baseColorUnif = glGetUniformLocation(data.theProgram, “baseColor”);glUniformBlockBinding(data.theProgram, data.globalUniformBlockIndex, g_iGlobalMatricesBindingIndex);
return data;
}void InitializeProgram()
{
UniformColor = LoadProgram(“PosOnlyWorldTransformUBO.vert”, “ColorUniform.frag”);
ObjectColor = LoadProgram(“PosColorWorldTransformUBO.vert”, “ColorPassthrough.frag”);
UniformColorTint = LoadProgram(“PosColorWorldTransformUBO.vert”, “ColorMultUniform.frag”);glGenBuffers(1, &g_GlobalMatricesUBO);
glBindBuffer(GL_UNIFORM_BUFFER, g_GlobalMatricesUBO);
glBufferData(GL_UNIFORM_BUFFER, sizeof(glm::mat4) * 2, NULL, GL_STREAM_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);glBindBufferRange(GL_UNIFORM_BUFFER, g_iGlobalMatricesBindingIndex, g_GlobalMatricesUBO,
0, sizeof(glm::mat4) * 2);
}glm::mat4 CalcLookAtMatrix(const glm::vec3 &cameraPt, const glm::vec3 &lookPt, const glm::vec3 &upPt)
{
glm::vec3 lookDir = glm::normalize(lookPt - cameraPt);
glm::vec3 upDir = glm::normalize(upPt);glm::vec3 rightDir = glm::normalize(glm::cross(lookDir, upDir));
glm::vec3 perpUpDir = glm::cross(rightDir, lookDir);glm::mat4 rotMat(1.0f);
rotMat[0] = glm::vec4(rightDir, 0.0f);
rotMat[1] = glm::vec4(perpUpDir, 0.0f);
rotMat[2] = glm::vec4(-lookDir, 0.0f);rotMat = glm::transpose(rotMat);
glm::mat4 transMat(1.0f);
transMat[3] = glm::vec4(-cameraPt, 1.0f);return rotMat * transMat;
}Framework::Mesh *g_pConeMesh = NULL;
Framework::Mesh *g_pCylinderMesh = NULL;
Framework::Mesh *g_pCubeTintMesh = NULL;
Framework::Mesh *g_pCubeColorMesh = NULL;
Framework::Mesh *g_pPlaneMesh = NULL;//Called after the window and OpenGL are initialized. Called exactly once, before the main loop.
void init()
{
InitializeProgram();try
{
g_pConeMesh = new Framework::Mesh(“UnitConeTint.xml”);
g_pCylinderMesh = new Framework::Mesh(“UnitCylinderTint.xml”);
g_pCubeTintMesh = new Framework::Mesh(“UnitCubeTint.xml”);
g_pCubeColorMesh = new Framework::Mesh(“UnitCubeColor.xml”);
g_pPlaneMesh = new Framework::Mesh(“UnitPlane.xml”);
}
catch(std::exception &except)
{
printf("%s
", except.what());
throw;
}glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CW);glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glDepthFunc(GL_LEQUAL);
glDepthRange(0.0f, 1.0f);
glEnable(GL_DEPTH_CLAMP);
}static float g_fYAngle = 0.0f;
static float g_fXAngle = 0.0f;//Trees are 3x3 in X/Z, and fTrunkHeight+fConeHeight in the Y.
void DrawTree(glutil::MatrixStack &modelMatrix, float fTrunkHeight = 2.0f, float fConeHeight = 3.0f)
{
//Draw trunk.
{
glutil::PushStack push(modelMatrix);modelMatrix.Scale(glm::vec3(1.0f, fTrunkHeight, 1.0f)); modelMatrix.Translate(glm::vec3(0.0f, 0.5f, 0.0f)); glUseProgram(UniformColorTint.theProgram); glUniformMatrix4fv(UniformColorTint.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top())); glUniform4f(UniformColorTint.baseColorUnif, 0.694f, 0.4f, 0.106f, 1.0f); g_pCylinderMesh->Render(); glUseProgram(0);
}
//Draw the treetop
{
glutil::PushStack push(modelMatrix);modelMatrix.Translate(glm::vec3(0.0f, fTrunkHeight, 0.0f)); modelMatrix.Scale(glm::vec3(3.0f, fConeHeight, 3.0f)); glUseProgram(UniformColorTint.theProgram); glUniformMatrix4fv(UniformColorTint.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top())); glUniform4f(UniformColorTint.baseColorUnif, 0.0f, 1.0f, 0.0f, 1.0f); g_pConeMesh->Render(); glUseProgram(0);
}
}const float g_fColumnBaseHeight = 0.25f;
//Columns are 1x1 in the X/Z, and fHieght units in the Y.
void DrawColumn(glutil::MatrixStack &modelMatrix, float fHeight = 5.0f)
{
//Draw the bottom of the column.
{
glutil::PushStack push(modelMatrix);modelMatrix.Scale(glm::vec3(1.0f, g_fColumnBaseHeight, 1.0f)); modelMatrix.Translate(glm::vec3(0.0f, 0.5f, 0.0f)); glUseProgram(UniformColorTint.theProgram); glUniformMatrix4fv(UniformColorTint.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top())); glUniform4f(UniformColorTint.baseColorUnif, 1.0f, 1.0f, 1.0f, 1.0f); g_pCubeTintMesh->Render(); glUseProgram(0);
}
//Draw the top of the column.
{
glutil::PushStack push(modelMatrix);modelMatrix.Translate(glm::vec3(0.0f, fHeight - g_fColumnBaseHeight, 0.0f)); modelMatrix.Scale(glm::vec3(1.0f, g_fColumnBaseHeight, 1.0f)); modelMatrix.Translate(glm::vec3(0.0f, 0.5f, 0.0f)); glUseProgram(UniformColorTint.theProgram); glUniformMatrix4fv(UniformColorTint.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top())); glUniform4f(UniformColorTint.baseColorUnif, 0.9f, 0.9f, 0.9f, 0.9f); g_pCubeTintMesh->Render(); glUseProgram(0);
}
//Draw the main column.
{
glutil::PushStack push(modelMatrix);modelMatrix.Translate(glm::vec3(0.0f, g_fColumnBaseHeight, 0.0f)); modelMatrix.Scale(glm::vec3(0.8f, fHeight - (g_fColumnBaseHeight * 2.0f), 0.8f)); modelMatrix.Translate(glm::vec3(0.0f, 0.5f, 0.0f)); glUseProgram(UniformColorTint.theProgram); glUniformMatrix4fv(UniformColorTint.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top())); glUniform4f(UniformColorTint.baseColorUnif, 0.9f, 0.9f, 0.9f, 0.9f); g_pCylinderMesh->Render(); glUseProgram(0);
}
}const float g_fParthenonWidth = 14.0f;
const float g_fParthenonLength = 20.0f;
const float g_fParthenonColumnHeight = 5.0f;
const float g_fParthenonBaseHeight = 1.0f;
const float g_fParthenonTopHeight = 2.0f;void DrawParthenon(glutil::MatrixStack &modelMatrix)
{
//Draw base.
{
glutil::PushStack push(modelMatrix);modelMatrix.Scale(glm::vec3(g_fParthenonWidth, g_fParthenonBaseHeight, g_fParthenonLength)); modelMatrix.Translate(glm::vec3(0.0f, 0.5f, 0.0f)); glUseProgram(UniformColorTint.theProgram); glUniformMatrix4fv(UniformColorTint.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top())); glUniform4f(UniformColorTint.baseColorUnif, 0.9f, 0.9f, 0.9f, 0.9f); g_pCubeTintMesh->Render(); glUseProgram(0);
}
//Draw top.
{
glutil::PushStack push(modelMatrix);modelMatrix.Translate(glm::vec3(0.0f, g_fParthenonColumnHeight + g_fParthenonBaseHeight, 0.0f)); modelMatrix.Scale(glm::vec3(g_fParthenonWidth, g_fParthenonTopHeight, g_fParthenonLength)); modelMatrix.Translate(glm::vec3(0.0f, 0.5f, 0.0f)); glUseProgram(UniformColorTint.theProgram); glUniformMatrix4fv(UniformColorTint.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top())); glUniform4f(UniformColorTint.baseColorUnif, 0.9f, 0.9f, 0.9f, 0.9f); g_pCubeTintMesh->Render(); glUseProgram(0);
}
//Draw columns.
const float fFrontZVal = (g_fParthenonLength / 2.0f) - 1.0f;
const float fRightXVal = (g_fParthenonWidth / 2.0f) - 1.0f;for(int iColumnNum = 0; iColumnNum < int(g_fParthenonWidth / 2.0f); iColumnNum++)
{
{
glutil::PushStack push(modelMatrix);
modelMatrix.Translate(glm::vec3((2.0f * iColumnNum) - (g_fParthenonWidth / 2.0f) + 1.0f,
g_fParthenonBaseHeight, fFrontZVal));DrawColumn(modelMatrix, g_fParthenonColumnHeight); } { glutil::PushStack push(modelMatrix); modelMatrix.Translate(glm::vec3((2.0f * iColumnNum) - (g_fParthenonWidth / 2.0f) + 1.0f, g_fParthenonBaseHeight, -fFrontZVal)); DrawColumn(modelMatrix, g_fParthenonColumnHeight); }
}
//Don’t draw the first or last columns, since they’ve been drawn already.
for(int iColumnNum = 1; iColumnNum < int((g_fParthenonLength - 2.0f) / 2.0f); iColumnNum++)
{
{
glutil::PushStack push(modelMatrix);
modelMatrix.Translate(glm::vec3(fRightXVal,
g_fParthenonBaseHeight, (2.0f * iColumnNum) - (g_fParthenonLength / 2.0f) + 1.0f));DrawColumn(modelMatrix, g_fParthenonColumnHeight); } { glutil::PushStack push(modelMatrix); modelMatrix.Translate(glm::vec3(-fRightXVal, g_fParthenonBaseHeight, (2.0f * iColumnNum) - (g_fParthenonLength / 2.0f) + 1.0f)); DrawColumn(modelMatrix, g_fParthenonColumnHeight); }
}
//Draw interior.
{
glutil::PushStack push(modelMatrix);modelMatrix.Translate(glm::vec3(0.0f, 1.0f, 0.0f)); modelMatrix.Scale(glm::vec3(g_fParthenonWidth - 6.0f, g_fParthenonColumnHeight, g_fParthenonLength - 6.0f)); modelMatrix.Translate(glm::vec3(0.0f, 0.5f, 0.0f)); glUseProgram(ObjectColor.theProgram); glUniformMatrix4fv(ObjectColor.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top())); g_pCubeColorMesh->Render(); glUseProgram(0);
}
//Draw headpiece.
{
glutil::PushStack push(modelMatrix);modelMatrix.Translate(glm::vec3( 0.0f, g_fParthenonColumnHeight + g_fParthenonBaseHeight + (g_fParthenonTopHeight / 2.0f), g_fParthenonLength / 2.0f)); modelMatrix.RotateX(-135.0f); modelMatrix.RotateY(45.0f); glUseProgram(ObjectColor.theProgram); glUniformMatrix4fv(ObjectColor.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top())); g_pCubeColorMesh->Render(); glUseProgram(0);
}
}struct TreeData
{
float fXPos;
float fZPos;
float fTrunkHeight;
float fConeHeight;
};static const TreeData g_forest =
{
{25.0f, 5.0f, 2.0f, 3.0f},
{25.0f, 10.0f, 2.0f, 3.0f},
{25.0f, 15.0f, 2.0f, 3.0f},
{25.0f, 20.0f, 2.0f, 3.0f},
{25.0f, 25.0f, 2.0f, 3.0f},
{25.0f, 30.0f, 2.0f, 3.0f},
{25.0f, 35.0f, 2.0f, 3.0f},
{25.0f, 40.0f, 2.0f, 3.0f},
{25.0f, 45.0f, 2.0f, 3.0f},
};void DrawForest(glutil::MatrixStack &modelMatrix)
{
for(int iTree = 0; iTree < ARRAY_COUNT(g_forest); iTree++)
{
const TreeData &currTree = g_forest[iTree];glutil::PushStack push(modelMatrix); modelMatrix.Translate(glm::vec3(currTree.fXPos, 0.0f, currTree.fZPos)); DrawTree(modelMatrix, currTree.fTrunkHeight, currTree.fConeHeight);
}
}static bool g_bDrawLookatPoint = false;
static glm::vec3 g_camTarget(0.0f, 0.4f, 0.0f);//In spherical coordinates.
static glm::vec3 g_sphereCamRelPos(67.5f, -46.0f, 150.0f);glm::vec3 ResolveCamPosition()
{
glutil::MatrixStack tempMat;float phi = Framework::DegToRad(g_sphereCamRelPos.x);
float theta = Framework::DegToRad(g_sphereCamRelPos.y + 90.0f);float fSinTheta = sinf(theta);
float fCosTheta = cosf(theta);
float fCosPhi = cosf(phi);
float fSinPhi = sinf(phi);glm::vec3 dirToCamera(fSinTheta * fCosPhi, fCosTheta, fSinTheta * fSinPhi);
return (dirToCamera * g_sphereCamRelPos.z) + g_camTarget;
}//Called to update the display.
//You should call glutSwapBuffers after all of your rendering to display what you rendered.
//If you need continuous updates of the screen, call glutPostRedisplay() at the end of the function.
void display()
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);if(g_pConeMesh && g_pCylinderMesh && g_pCubeTintMesh && g_pCubeColorMesh && g_pPlaneMesh)
{
const glm::vec3 &camPos = ResolveCamPosition();glutil::MatrixStack camMatrix; camMatrix.SetMatrix(CalcLookAtMatrix(camPos, g_camTarget, glm::vec3(0.0f, 1.0f, 0.0f))); glBindBuffer(GL_UNIFORM_BUFFER, g_GlobalMatricesUBO); glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(camMatrix.Top())); glBindBuffer(GL_UNIFORM_BUFFER, 0); glutil::MatrixStack modelMatrix; //Render the ground plane. { glutil::PushStack push(modelMatrix); modelMatrix.Scale(glm::vec3(100.0f, 1.0f, 100.0f)); glUseProgram(UniformColor.theProgram); glUniformMatrix4fv(UniformColor.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top())); glUniform4f(UniformColor.baseColorUnif, 0.302f, 0.416f, 0.0589f, 1.0f); g_pPlaneMesh->Render(); glUseProgram(0); } //Draw the trees DrawForest(modelMatrix); //Draw the building. { glutil::PushStack push(modelMatrix); modelMatrix.Translate(glm::vec3(20.0f, 0.0f, -10.0f)); DrawParthenon(modelMatrix); } if(g_bDrawLookatPoint) { glDisable(GL_DEPTH_TEST); glutil::PushStack push(modelMatrix); modelMatrix.Translate(g_camTarget); modelMatrix.Scale(1.0f, 1.0f, 1.0f); glUseProgram(ObjectColor.theProgram); glUniformMatrix4fv(ObjectColor.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top())); g_pCubeColorMesh->Render(); glUseProgram(0); glEnable(GL_DEPTH_TEST); }
}
glutSwapBuffers();
}//Called whenever the window is resized. The new window size is given, in pixels.
//This is an opportunity to call glViewport or glScissor to keep up with the change in size.
void reshape (int w, int h)
{
glutil::MatrixStack persMatrix;
persMatrix.Perspective(45.0f, (w / (float)h), g_fzNear, g_fzFar);glBindBuffer(GL_UNIFORM_BUFFER, g_GlobalMatricesUBO);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(glm::mat4), glm::value_ptr(persMatrix.Top()));
glBindBuffer(GL_UNIFORM_BUFFER, 0);glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glutPostRedisplay();
}//Called whenever a key on the keyboard was pressed.
//The key is given by the ‘‘key’’ parameter, which is in ASCII.
//It’s often a good idea to have the escape key (ASCII value 27) call glutLeaveMainLoop() to
//exit the program.
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case 27:
delete g_pConeMesh;
g_pConeMesh = NULL;
delete g_pCylinderMesh;
g_pCylinderMesh = NULL;
delete g_pCubeTintMesh;
g_pCubeTintMesh = NULL;
delete g_pCubeColorMesh;
g_pCubeColorMesh = NULL;
delete g_pPlaneMesh;
g_pPlaneMesh = NULL;
glutLeaveMainLoop();
return;
case ‘w’: g_camTarget.z -= 4.0f; break;
case ‘s’: g_camTarget.z += 4.0f; break;
case ‘d’: g_camTarget.x += 4.0f; break;
case ‘a’: g_camTarget.x -= 4.0f; break;
case ‘e’: g_camTarget.y -= 4.0f; break;
case ‘q’: g_camTarget.y += 4.0f; break;
case ‘W’: g_camTarget.z -= 0.4f; break;
case ‘S’: g_camTarget.z += 0.4f; break;
case ‘D’: g_camTarget.x += 0.4f; break;
case ‘A’: g_camTarget.x -= 0.4f; break;
case ‘E’: g_camTarget.y -= 0.4f; break;
case ‘Q’: g_camTarget.y += 0.4f; break;
case ‘i’: g_sphereCamRelPos.y -= 11.25f; break;
case ‘k’: g_sphereCamRelPos.y += 11.25f; break;
case ‘j’: g_sphereCamRelPos.x -= 11.25f; break;
case ‘l’: g_sphereCamRelPos.x += 11.25f; break;
case ‘o’: g_sphereCamRelPos.z -= 5.0f; break;
case ‘u’: g_sphereCamRelPos.z += 5.0f; break;
case ‘I’: g_sphereCamRelPos.y -= 1.125f; break;
case ‘K’: g_sphereCamRelPos.y += 1.125f; break;
case ‘J’: g_sphereCamRelPos.x -= 1.125f; break;
case ‘L’: g_sphereCamRelPos.x += 1.125f; break;
case ‘O’: g_sphereCamRelPos.z -= 0.5f; break;
case ‘U’: g_sphereCamRelPos.z += 0.5f; break;case 32:
g_bDrawLookatPoint = !g_bDrawLookatPoint;
printf("Target: %f, %f, %f
", g_camTarget.x, g_camTarget.y, g_camTarget.z);
printf("Position: %f, %f, %f
", g_sphereCamRelPos.x, g_sphereCamRelPos.y, g_sphereCamRelPos.z);
break;
}g_sphereCamRelPos.y = glm::clamp(g_sphereCamRelPos.y, -78.75f, -1.0f);
g_camTarget.y = g_camTarget.y > 0.0f ? g_camTarget.y : 0.0f;
g_sphereCamRelPos.z = g_sphereCamRelPos.z > 5.0f ? g_sphereCamRelPos.z : 5.0f;glutPostRedisplay();
}unsigned int defaults(unsigned int displayMode, int &width, int &height) {return displayMode;}
It’s so much text, but it’s just plain colors… Tutorial 9 on that site explains how to do lightning effects, but … that one goes like this:
ColorPassthrough.frag: <same as before>
DirVertexLighting_PN.vert:
#version 330
layout(location = 0) in vec3 position;
layout(location = 2) in vec3 normal;smooth out vec4 interpColor;
uniform vec3 dirToLight;
uniform vec4 lightIntensity;uniform mat4 modelToCameraMatrix;
uniform mat3 normalModelToCameraMatrix;layout(std140) uniform Projection
{
mat4 cameraToClipMatrix;
};void main()
{
gl_Position = cameraToClipMatrix * (modelToCameraMatrix * vec4(position, 1.0));vec3 normCamSpace = normalize(normalModelToCameraMatrix * normal);
float cosAngIncidence = dot(normCamSpace, dirToLight);
cosAngIncidence = clamp(cosAngIncidence, 0, 1);interpColor = lightIntensity * cosAngIncidence;
}
DirVertexLighting_PCN.vert:
#version 330
layout(location = 0) in vec3 position;
layout(location = 1) in vec4 diffuseColor;
layout(location = 2) in vec3 normal;smooth out vec4 interpColor;
uniform vec3 dirToLight;
uniform vec4 lightIntensity;uniform mat4 modelToCameraMatrix;
uniform mat3 normalModelToCameraMatrix;layout(std140) uniform Projection
{
mat4 cameraToClipMatrix;
};void main()
{
gl_Position = cameraToClipMatrix * (modelToCameraMatrix * vec4(position, 1.0));vec3 normCamSpace = normalize(normalModelToCameraMatrix * normal);
float cosAngIncidence = dot(normCamSpace, dirToLight);
cosAngIncidence = clamp(cosAngIncidence, 0, 1);interpColor = lightIntensity * diffuseColor * cosAngIncidence;
}
Basic Lightning.cpp:
//Copyright (C) 2010-2012 by Jason L. McKesson
//This file is licensed under the MIT License.#include <string>
#include <vector>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <glload/gl_3_3.h>
#include <glutil/glutil.h>
#include <GL/freeglut.h>
#include “…/framework/framework.h”
#include “…/framework/Mesh.h”
#include “…/framework/MousePole.h”
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>#define ARRAY_COUNT( array ) (sizeof( array ) / (sizeof( array[0] ) * (sizeof( array ) != sizeof(void*) || sizeof( array[0] ) <= sizeof(void*))))
struct ProgramData
{
GLuint theProgram;GLuint dirToLightUnif;
GLuint lightIntensityUnif;GLuint modelToCameraMatrixUnif;
GLuint normalModelToCameraMatrixUnif;
};float g_fzNear = 1.0f;
float g_fzFar = 1000.0f;ProgramData g_WhiteDiffuseColor;
ProgramData g_VertexDiffuseColor;const int g_projectionBlockIndex = 2;
ProgramData LoadProgram(const std::string &strVertexShader, const std::string &strFragmentShader)
{
std::vector<GLuint> shaderList;shaderList.push_back(Framework::LoadShader(GL_VERTEX_SHADER, strVertexShader));
shaderList.push_back(Framework::LoadShader(GL_FRAGMENT_SHADER, strFragmentShader));ProgramData data;
data.theProgram = Framework::CreateProgram(shaderList);
data.modelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, “modelToCameraMatrix”);
data.normalModelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, “normalModelToCameraMatrix”);
data.dirToLightUnif = glGetUniformLocation(data.theProgram, “dirToLight”);
data.lightIntensityUnif = glGetUniformLocation(data.theProgram, “lightIntensity”);GLuint projectionBlock = glGetUniformBlockIndex(data.theProgram, “Projection”);
glUniformBlockBinding(data.theProgram, projectionBlock, g_projectionBlockIndex);return data;
}void InitializeProgram()
{
g_WhiteDiffuseColor = LoadProgram(“DirVertexLighting_PN.vert”, “ColorPassthrough.frag”);
g_VertexDiffuseColor = LoadProgram(“DirVertexLighting_PCN.vert”, “ColorPassthrough.frag”);
}Framework::Mesh *g_pCylinderMesh = NULL;
Framework::Mesh *g_pPlaneMesh = NULL;///////////////////////////////////////////////
// View/Object Setup
glutil::ViewData g_initialViewData =
{
glm::vec3(0.0f, 0.5f, 0.0f),
glm::fquat(0.92387953f, 0.3826834f, 0.0f, 0.0f),
5.0f,
0.0f
};glutil::ViewScale g_viewScale =
{
3.0f, 20.0f,
1.5f, 0.5f,
0.0f, 0.0f, //No camera movement.
90.0f/250.0f
};glutil::ObjectData g_initialObjectData =
{
glm::vec3(0.0f, 0.5f, 0.0f),
glm::fquat(1.0f, 0.0f, 0.0f, 0.0f),
};glutil::ViewPole g_viewPole = glutil::ViewPole(g_initialViewData,
g_viewScale, glutil::MB_LEFT_BTN);
glutil::ObjectPole g_objtPole = glutil::ObjectPole(g_initialObjectData,
90.0f/250.0f, glutil::MB_RIGHT_BTN, &g_viewPole);namespace
{
void MouseMotion(int x, int y)
{
Framework::ForwardMouseMotion(g_viewPole, x, y);
Framework::ForwardMouseMotion(g_objtPole, x, y);
glutPostRedisplay();
}void MouseButton(int button, int state, int x, int y)
{
Framework::ForwardMouseButton(g_viewPole, button, state, x, y);
Framework::ForwardMouseButton(g_objtPole, button, state, x, y);
glutPostRedisplay();
}void MouseWheel(int wheel, int direction, int x, int y)
{
Framework::ForwardMouseWheel(g_viewPole, wheel, direction, x, y);
Framework::ForwardMouseWheel(g_objtPole, wheel, direction, x, y);
glutPostRedisplay();
}
}GLuint g_projectionUniformBuffer = 0;
struct ProjectionBlock
{
glm::mat4 cameraToClipMatrix;
};//Called after the window and OpenGL are initialized. Called exactly once, before the main loop.
void init()
{
InitializeProgram();try
{
g_pCylinderMesh = new Framework::Mesh(“UnitCylinder.xml”);
g_pPlaneMesh = new Framework::Mesh(“LargePlane.xml”);
}
catch(std::exception &except)
{
printf("%s
", except.what());
throw;
}glutMouseFunc(MouseButton);
glutMotionFunc(MouseMotion);
glutMouseWheelFunc(MouseWheel);glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CW);glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glDepthFunc(GL_LEQUAL);
glDepthRange(0.0f, 1.0f);
glEnable(GL_DEPTH_CLAMP);glGenBuffers(1, &g_projectionUniformBuffer);
glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
glBufferData(GL_UNIFORM_BUFFER, sizeof(ProjectionBlock), NULL, GL_DYNAMIC_DRAW);//Bind the static buffers.
glBindBufferRange(GL_UNIFORM_BUFFER, g_projectionBlockIndex, g_projectionUniformBuffer,
0, sizeof(ProjectionBlock));glBindBuffer(GL_UNIFORM_BUFFER, 0);
}glm::vec4 g_lightDirection(0.866f, 0.5f, 0.0f, 0.0f);
static bool g_bDrawColoredCyl = true;
//Called to update the display.
//You should call glutSwapBuffers after all of your rendering to display what you rendered.
//If you need continuous updates of the screen, call glutPostRedisplay() at the end of the function.
void display()
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);if(g_pPlaneMesh && g_pCylinderMesh)
{
glutil::MatrixStack modelMatrix;
modelMatrix.SetMatrix(g_viewPole.CalcMatrix());glm::vec4 lightDirCameraSpace = modelMatrix.Top() * g_lightDirection; glUseProgram(g_WhiteDiffuseColor.theProgram); glUniform3fv(g_WhiteDiffuseColor.dirToLightUnif, 1, glm::value_ptr(lightDirCameraSpace)); glUseProgram(g_VertexDiffuseColor.theProgram); glUniform3fv(g_VertexDiffuseColor.dirToLightUnif, 1, glm::value_ptr(lightDirCameraSpace)); glUseProgram(0); { glutil::PushStack push(modelMatrix); //Render the ground plane. { glutil::PushStack push(modelMatrix); glUseProgram(g_WhiteDiffuseColor.theProgram); glUniformMatrix4fv(g_WhiteDiffuseColor.modelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top())); glm::mat3 normMatrix(modelMatrix.Top()); glUniformMatrix3fv(g_WhiteDiffuseColor.normalModelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(normMatrix)); glUniform4f(g_WhiteDiffuseColor.lightIntensityUnif, 1.0f, 1.0f, 1.0f, 1.0f); g_pPlaneMesh->Render(); glUseProgram(0); } //Render the Cylinder { glutil::PushStack push(modelMatrix); modelMatrix.ApplyMatrix(g_objtPole.CalcMatrix()); if(g_bDrawColoredCyl) { glUseProgram(g_VertexDiffuseColor.theProgram); glUniformMatrix4fv(g_VertexDiffuseColor.modelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top())); glm::mat3 normMatrix(modelMatrix.Top()); glUniformMatrix3fv(g_VertexDiffuseColor.normalModelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(normMatrix)); glUniform4f(g_VertexDiffuseColor.lightIntensityUnif, 1.0f, 1.0f, 1.0f, 1.0f); g_pCylinderMesh->Render("lit-color"); } else { glUseProgram(g_WhiteDiffuseColor.theProgram); glUniformMatrix4fv(g_WhiteDiffuseColor.modelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top())); glm::mat3 normMatrix(modelMatrix.Top()); glUniformMatrix3fv(g_WhiteDiffuseColor.normalModelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(normMatrix)); glUniform4f(g_WhiteDiffuseColor.lightIntensityUnif, 1.0f, 1.0f, 1.0f, 1.0f); g_pCylinderMesh->Render("lit"); } glUseProgram(0); } }
}
glutSwapBuffers();
}//Called whenever the window is resized. The new window size is given, in pixels.
//This is an opportunity to call glViewport or glScissor to keep up with the change in size.
void reshape (int w, int h)
{
glutil::MatrixStack persMatrix;
persMatrix.Perspective(45.0f, (w / (float)h), g_fzNear, g_fzFar);ProjectionBlock projData;
projData.cameraToClipMatrix = persMatrix.Top();glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(ProjectionBlock), &projData);
glBindBuffer(GL_UNIFORM_BUFFER, 0);glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glutPostRedisplay();
}//Called whenever a key on the keyboard was pressed.
//The key is given by the ‘‘key’’ parameter, which is in ASCII.
//It’s often a good idea to have the escape key (ASCII value 27) call glutLeaveMainLoop() to
//exit the program.
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case 27:
delete g_pPlaneMesh;
delete g_pCylinderMesh;
glutLeaveMainLoop();
return;case 32:
g_bDrawColoredCyl = !g_bDrawColoredCyl;
break;
}glutPostRedisplay();
}unsigned int defaults(unsigned int displayMode, int &width, int &height) {return displayMode;}
True, this isn’t for a whole scenery, it’s just for one object that is always the center of the camera, but I figured that if the tutorial touches upon this, then it should be a type of knowledge that can be combined with things learned before… it’s really not.
I tried adding adding GLuint dirToLightUnif and GLuint lightIntensityUnif to the ProgramData of the Tut7 and then work around that… didn’t work. Then I fiddled with the vertex shaders… still nothing… then I did so much different stuff… seriously the best result I ever got was creating ProgramData (from the tutorial about the scene) and ProgramData_2 (from the tutorial about lightning). With this I made this sort of thing:
(…)
//Render the ground plane.
{
glutil::PushStack push(modelMatrix);modelMatrix.Scale(glm::vec3(100.0f, 1.0f, 100.0f)); glUseProgram(UniformColor.theProgram); glUniformMatrix4fv(UniformColor.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top())); glUniform4f(UniformColor.baseColorUnif, 0.302f, 0.416f, 0.0589f, 1.0f); if(g_bDoInvTranspose) { glUseProgram(g_WhiteDiffuseColor.theProgram); glUniformMatrix4fv(g_WhiteDiffuseColor.modelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top())); glm::mat3 normMatrix(modelMatrix.Top()); glUniformMatrix3fv(g_WhiteDiffuseColor.normalModelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(normMatrix)); glUniform4f(g_WhiteDiffuseColor.lightIntensityUnif, 1.0f, 1.0f, 1.0f, 1.0f); }
g_pPlaneMesh->Render();
glUseProgram(0);
}
(…)
The “g_bDoInvTranspose” thing is a bool variable which switches values when the ‘t’ key is pressed. Surprisingly when it’s off, things render nicely as before, but if it’s on, the specific object is invisible! Even when I removed everything but the ‘glUseProgram(g_WhiteDiffuseColor.theProgram);’ line, it still was invisible.
I have spend more than 2 weeks on this already, no jokes at all, I’m frustrated with this, so here, I ask kindly, could anyone at all help me with this? How should I apply simple lightning to this big scene?