-
Sack TVLikes 0Problem Description
I'm following the Modern OpenGL YouTube-Tutorial from your YouTube-Channel. I created a class for cubes and lamps. To calculate the lighting on cubes the positions of the lights is needed. This position is a vec3 array. This is working fine, but when i have more then one light-object i would have to pass the cube two arrays, which I don't know how to do.
This is my code:
Cube class:
#include "cubeVertices.h"
#include "cube.hpp"
using namespace glm;
Cube::Cube(Shader shader):
shader(shader) {
glGenVertexArrays(1, &this->VAO);
glGenBuffers(1, &this->VBO);
glBindVertexArray(this->VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), cubeVertices, GL_STATIC_DRAW);
//Pos
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid *) 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid *) (3 * sizeof(GLfloat)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid *) (6 * sizeof(GLfloat)));
glEnableVertexAttribArray(2);
glBindVertexArray(0);
}
Cube::~Cube() {
glDeleteVertexArrays(1, &this->VAO);
glDeleteBuffers(1, &this->VBO);
}
void Cube::registerTexture(GLuint texture, const char* name) {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(glGetUniformLocation(shader.program, name), 0);
}
void Cube::render(GLfloat size, vec3 positions[], int amount, vec3 lightPos[], int lightAmount, float reflection, mat4 projection, Camera camera, bool spotLight) {
GLint viewPosLoc = glGetUniformLocation(shader.program, "viewPos");
glUniform3f(viewPosLoc, camera.getPosition().x, camera.getPosition().y, camera.getPosition().z);
GLint modelLoc = glGetUniformLocation(shader.program, "model");
GLint viewLoc = glGetUniformLocation(shader.program, "view");
GLint projLoc = glGetUniformLocation(shader.program, "projection");
for(int i = 0; i < lightAmount; i++) {
std::string pointLightBase = "pointLight[" + std::to_string(i) + "].";
glUniform3f(glGetUniformLocation(shader.program, (pointLightBase + "position").c_str()), lightPos[i].x, lightPos[i].y, lightPos[i].z);
glUniform3f(glGetUniformLocation(shader.program, (pointLightBase + "ambient").c_str()), 0.0f, 0.0f, 0.0f);
glUniform3f(glGetUniformLocation(shader.program, (pointLightBase + "diffuse").c_str()), 0.8f, 0.8f, 0.8f);
glUniform3f(glGetUniformLocation(shader.program, (pointLightBase + "specular").c_str()), 1.0f, 1.0f, 1.0f);
glUniform1f(glGetUniformLocation(shader.program, (pointLightBase + "constant").c_str()),1.0f);
glUniform1f(glGetUniformLocation(shader.program, (pointLightBase + "linear").c_str()), 0.0f);
glUniform1f(glGetUniformLocation(shader.program, (pointLightBase + "quadratic").c_str()), 0.032f);
}
if(spotLight) {
glUniform3f(glGetUniformLocation(shader.program, "spotLight.position"), camera.getPosition().x, camera.getPosition().y, camera.getPosition().z);
glUniform3f(glGetUniformLocation(shader.program, "spotLight.direction"), camera.getFront().x, camera.getFront().y, camera.getFront().z);
glUniform3f(glGetUniformLocation(shader.program, "spotLight.ambient"), 0.0f, 0.0f, 0.0f);
glUniform3f(glGetUniformLocation(shader.program, "spotLight.diffuse"), 0.8f, 0.8f, 0.8f);
glUniform3f(glGetUniformLocation(shader.program, "spotLight.specular"), 1.0f, 1.0f, 1.0f);
glUniform1f(glGetUniformLocation(shader.program, "spotLight.constant"), 1.0f);
glUniform1f(glGetUniformLocation(shader.program, "spotLight.linear"), 0.09f);
glUniform1f(glGetUniformLocation(shader.program, "spotLight.quadratic"), 0.032f);
glUniform1f(glGetUniformLocation(shader.program, "spotLight.cutOff"), cos(radians(12.5f)));
glUniform1f(glGetUniformLocation(shader.program, "spotLight.outerCutOff"), cos(radians(15.0f)));
}
else {
glUniform3f(glGetUniformLocation(shader.program, "spotLight.position"), camera.getPosition().x, camera.getPosition().y, camera.getPosition().z);
glUniform3f(glGetUniformLocation(shader.program, "spotLight.direction"), camera.getFront().x, camera.getFront().y, camera.getFront().z);
glUniform3f(glGetUniformLocation(shader.program, "spotLight.ambient"), 0.0f, 0.0f, 0.0f);
glUniform3f(glGetUniformLocation(shader.program, "spotLight.diffuse"), 0.0f, 0.0f, 0.0f);
glUniform3f(glGetUniformLocation(shader.program, "spotLight.specular"), 0.0f, 0.0f, 0.0f);
glUniform1f(glGetUniformLocation(shader.program, "spotLight.constant"), 1.0f);
glUniform1f(glGetUniformLocation(shader.program, "spotLight.linear"), 0.09f);
glUniform1f(glGetUniformLocation(shader.program, "spotLight.quadratic"), 0.032f);
glUniform1f(glGetUniformLocation(shader.program, "spotLight.cutOff"), cos(radians(20.0f)));
glUniform1f(glGetUniformLocation(shader.program, "spotLight.outerCutOff"), cos(radians(25.0f)));
}
glUniform1f(glGetUniformLocation(shader.program, "material.shininess"), reflection);
mat4 view(1);
view = camera.getViewMatrix();
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, value_ptr(projection));
glBindVertexArray(VAO);
for(int i = 0; i < amount; i++) {
mat4 model(1);
model = translate(model, positions[i]);
model = scale(model, vec3(size));
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, value_ptr(model));
glDrawArrays(GL_TRIANGLES, 0, 36);
}
glBindVertexArray(0);
}
Light class:
LuminousCube::LuminousCube(Shader shader):
shader(shader) {
glGenVertexArrays(1, &this->VAO);
glGenBuffers(1, &this->VBO);
glBindVertexArray(this->VAO);
glBindBuffer(GL_ARRAY_BUFFER, this->VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), cubeVertices, GL_STATIC_DRAW);
//Pos
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid *) 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
LuminousCube::~LuminousCube() {
glDeleteVertexArrays(1, &this->VAO);
glDeleteBuffers(1, &this->VBO);
}
void LuminousCube::render(GLfloat size, vec3 positions[], int amount, mat4 projection, Camera camera) {
mat4 view(1);
view = camera.getViewMatrix();
mat4 model(1);
GLint modelLoc = glGetUniformLocation(shader.program, "model");
GLint viewLoc = glGetUniformLocation(shader.program, "view");
GLint projLoc = glGetUniformLocation(shader.program, "projection");
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, value_ptr(view));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, value_ptr(projection));
glBindVertexArray(VAO);
for(int i = 0; i < amount; i++) {
mat4 model(1);
model = translate(model, positions[i]);
model = scale(model, vec3(size));
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, value_ptr(model));
glDrawArrays(GL_TRIANGLES, 0, 36);
}
glBindVertexArray(0);
}
Game-Loop in main.cpp:
while (!glfwWindowShouldClose(window)) {
GLfloat currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
glfwPollEvents();
doMovement();
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glfwGetFramebufferSize(window, &screenWidth, &screenHeight);
glViewport(0, 0, screenWidth, screenHeight);
mat4 projection = perspective(45.0f, (GLfloat)screenWidth / (GLfloat)screenHeight, 0.1f, 100.0f);
cubeShader.use();
cube1.registerTexture(texture1, "cube1");
cube1.render(1.0f, cubePos, sizeof(cubePos) / sizeof(vec3), lightPos, sizeof(lightPos) / sizeof(vec3), 30.0f, projection, camera, spotLight);
lightShader.use();
lamp1.render(3.1415f / 4, vec3(1.0f, 0.0f, 0.0f), vec3(0.2f), lightPos, sizeof(lightPos) / sizeof(vec3), projection, camera);
glfwSwapBuffers(window);
}
-
Sonar Systems adminLikes 0
Pass to the shader?
-
Sack TVLikes 0
I don't know if it is the correct english word, but the shader of the cube needs the positions of the lamps, this is what i mean by pass.
-
Sack TVLikes 0
Edit: i solved this issue.
Also, I get another problem, I give the cube shader the light positions. I have 2 dice objects and 2 lamp objects. The first cube object receives the light positions of the first light object, the second cube object receives the light positions of the second light object. But also the second cube objects are illuminated by the first light objects and not by the second, how can I change that?
-
Sonar Systems adminLikes 0
Can you show me the result and code.
-
Sack TVLikes 0
The code has not changed, I deleted a part of the cube code due to an earlier test, the code above works.
My approach to multiple light objects is to merge the light fields and then pass the merged fields to the cube shader. I think it would work, but I have some errors, maybe you can help me solve the problems.
I made this function to merge two arrays: Edit this is fixed
int * combine arrays (int * array1, int * array2, const int array1Size, const int array2Size) {
static int result [7] = {0};
for (int i = 0; i
result [i] = array1 [i];
}
for (int i = array1Size; i
result [i] = array2 [i - array1Size];
}
return result;
}
It works, but the problem is that the size of the result is fixed and I do not know how to use the array sizes of the arrays to be merged, which are passed into the function, because this:
static int result[array1Size + array2Size]; doesn't work.Is there a way to pass the number of point lights to the fragment shader of the cube? Because now, the number of point lights is just a define.
-
Sack TVLikes 0
Can you please just send me the code HERE, i don’t want to watch a 45 minute video for a few lines of code.
-
Sonar Systems adminLikes 0
-
Sack TVLikes 0
I DON’T want the array-size as a define, i asked if there is a way to pass the shader the array-size.
-
Sonar Systems adminLikes 0
?
-
Sack TVLikes 0
Is there a way to pass the shader the number of point lights other than with a define?
-
Sonar Systems adminLikes 0
A regular variable
-
Sack TVLikes 0
But how, I tried this:
uniform const int arraySize;
but it doesn't work.
-
Sonar Systems adminLikes 0
What happens?
-
Sack TVLikes 0
Nothing, i just get an error that this is not right, I need a way to pass in a const int.
-
Sonar Systems adminLikes 0
What’s the exact error?
-
Sack TVLikes 0
Seriously, can you just send me the code to pass a const int into the shader?
But here the eroor: Infolog: ERROR: 0:45: storage modifier qualifier 'const' must precede storage qualifiers
-
Sonar Systems adminLikes 0
This link will help you https://stackoverflow.com/questions/38281731/how-to-send-const-data-to-shaders
-
Sack TVLikes 0
Thank you
-
Sonar Systems adminLikes 0
You are very welcome.
Login to reply