/r/opengl

Photograph via snooOG

News, information and discussion about OpenGL development.

/r/opengl

28,652 Subscribers

3 Comments
2024/12/03
03:01 UTC

0

Shader Programming

I have 2 questions: Is it possible to compile and implement your own shaders using just the base installation of OpenGL? And how does one write to the frame buffer from the fragment shader?

2 Comments
2024/12/03
02:36 UTC

1

Compiling Shaders

I have taken an interest in graphics programming, and I'm learning about Vertex and Fragment shaders. I have 2 questions: Is there no way to make your own shaders using the base installation of OpenGL? And how does one write directly to the frame buffer from the fragment shader?

7 Comments
2024/12/03
02:31 UTC

5

Struggling with rendering multiple objects with single VAO VBO EBO

Hey,

I'm trying to render multiple objects with single VAO, VBO, and EBO buffers. I implemented the reallocate method for buffers, it should work fine. I think the problem is in another place, I hope you can help me.

The second mesh (the backpack) uses first model vertices (the floor)

Render code (simplified):

unsigned int indicesOffset = 0;
VAO.Bind();
for (auto mesh : meshes)
{
  shader.SetUniform("u_Model", mesh.transform);
  glDrawElements(GL_TRIANGLES, mesh.indices, GL_UNSIGNED_INT, (void *)(offsetIndices * sizeof(unsigned int)));
  offsetIndices += mesh.indices;
}

Add model:

m_VAO.Bind();
m_VBO.Bind();
m_VBO.Push(Vertices);
m_EBO.Bind();
m_EBO.Push(Indices);

m_VAO.EnableVertexAttrib(0, 3, GL_FLOAT, sizeof(shared::TVertex), (void *)offsetof(shared::TVertex, Position));
m_VAO.EnableVertexAttrib(1, 3, GL_FLOAT, sizeof(shared::TVertex), (void *)offsetof(shared::TVertex, Normal));
m_VAO.EnableVertexAttrib(2, 2, GL_FLOAT, sizeof(shared::TVertex), (void *)offsetof(shared::TVertex, TexCoords));

m_VAO.Unbind();

Buffer realloc method (VBO, EBO):

GLuint NewBufferID = 0;
glGenBuffers(1, &NewBufferID);
glBindBuffer(m_Target, NewBufferID);
glBufferData(m_Target, NewBufferCapacity, nullptr, m_Usage);

glBindBuffer(GL_COPY_READ_BUFFER,  m_ID);
glBindBuffer(GL_COPY_WRITE_BUFFER, NewBufferID);
glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, m_ActualSize);
glBindBuffer(GL_COPY_READ_BUFFER, 0);
glBindBuffer(GL_COPY_WRITE_BUFFER, 0);
glDeleteBuffers(1, &m_ID);
m_ID = NewBufferID;
m_Capacity = NewBufferCapacity;

Buffer::Push method:

void * MemPtr = glMapBuffer(m_Target, GL_WRITE_ONLY);
memcpy(((int8_t*)MemPtr + m_ActualSize), _Data, DataSizeInBytes);
glUnmapBuffer(m_Target);

m_ActualSize += DataSizeInBytes;

What could it be? Thanks.

2 Comments
2024/12/02
16:48 UTC

3

are the mingw gl header files for opengl 1.x and if so how do I use the later specifications?

4 Comments
2024/12/02
04:45 UTC

3

Synchronize 3D texture pixel across instances of compute shader?

I have a 3D texture with lighting values that I want to spread out, like Minecraft. I am using a compute shader for this. There's one shader that casts skylight onto the texture, then the other shader spreads out that skylight along with light-emitting blocks. The issue is synchronization. I've seen that I can use atomic operations on images, but those require the format to be int/uint, and I can't do that for 3D textures. Is there a way (something similar to Java synchronization) to prevent other instances of the compute shader from accessing a specific pixel of the texture?

5 Comments
2024/12/01
18:39 UTC

0

Struggling to rotate camera around point

I want my camera to face the player and when the middle mouse button is held down the camera rotates around the player based on mouse movement.

I am finding it really hard to do this.

Here is the relevant code:

Setting up the camera:

this->camera = Camera(dt::vec3f(-5, 10, -5));
this->camera.setFOV(45);
this->camera.setPerspectiveMatrix(this->window.getDimentions(), 0.00001, UINT64_MAX);

uint64_t creatureIndex;
this->world.findCreatureIndex(this->world.getPlayer().getCreatureId(), creatureIndex);
this->camera.lookAtPoint(dt::vec3f(this->world.getChunks()[0].getCreatures()[creatureIndex].getPos().x, this->world.getChunks()[0].getCreatures()[creatureIndex].getPos().y, this->world.getChunks()[0].getCreatures()[creatureIndex].getPos().z), this->window.getDimentions());

this->camera.setView(dt::mat4());
this->camera.checkForTranslation(this->inputControl.getKeybindings(), this->camera.getDepthBounds().y,this->settings,this->tick, dt::vec3uis(0, 0, 0), this->window);
this->camera.checkForRotation(this->inputControl.getKeybindings(), this->window, this->settings,dt::vec3uis(0,0,0));

Called every frame:

uint64_t creatureIndex;
if (this->world.findCreatureIndex(this->world.getPlayer().getCreatureId(), creatureIndex)) {
this->camera.translateToPoint(dt::vec3f(this->world.getChunks()[0].getCreatures()[creatureIndex].getPos().x, this->world.getChunks()[0].getCreatures()[creatureIndex].getPos().y, this->world.getChunks()[0].getCreatures()[creatureIndex].getPos().z));

this->camera.checkForRotation(this->inputControl.getKeybindings(), this->window, this->settings, this->world.getChunks()[0].getCreatures()[creatureIndex].getPos());
this->camera.translateToPoint(dt::vec3f(-this->world.getChunks()[0].getCreatures()[creatureIndex].getPos().x, -this->world.getChunks()[0].getCreatures()[creatureIndex].getPos().y, -this->world.getChunks()[0].getCreatures()[creatureIndex].getPos().z));
this->camera.checkForTranslation(this->inputControl.getKeybindings(), this->camera.getDepthBounds().y, this->settings, this->tick, this->world.getChunks()[0].getCreatures()[creatureIndex].getPos(), this->window);
}

Look at point:

void Camera::lookAtPoint(dt::vec3f targetPoint, dt::vec2i windowDimentions) {
this->rot.x = 310;
this->rot.y = 0;
}

Translate to point:

void Camera::translateToPoint(dt::vec3f point) {
Cross crossHandle; Normalise normHandle; Dot dotHandle;

this->target.x = cos(this->rot.x * (M_PI / 180)) * sin(this->rot.y * (M_PI / 180));
this->target.y = sin(this->rot.x * (M_PI / 180));
this->target.z = cos(this->rot.x * (M_PI / 180)) * cos(this->rot.y * (M_PI / 180));

dt::vec3f p = normHandle.normalize3D(point, this->depthBounds.y);

this->forward.x = (p.x - this->target.x);
this->forward.y = (p.y - this->target.y);
this->forward.z = (p.z - this->target.z);


dt::vec3f right = dt::vec3f(0, 0, 0);
right.x = sin((this->rot.y * (M_PI / 180)) - M_PI / 2.0);
right.y = 0;
right.z = cos((this->rot.y * (M_PI / 180)) - M_PI / 2.0);


this->up = crossHandle.findCrossProduct(this->forward, right);

dt::mat4 mat;
mat.mat[0][0] = right.x;
mat.mat[0][1] = right.y;
mat.mat[0][2] = right.z;

mat.mat[1][0] = this->up.x;
mat.mat[1][1] = this->up.y;
mat.mat[1][2] = this->up.z;

mat.mat[2][0] = -this->forward.x;
mat.mat[2][1] = -this->forward.y;
mat.mat[2][2] = -this->forward.z;

mat.mat[0][3] = -dotHandle.calculateDotProduct3D(this->pos, right);
mat.mat[1][3] = -dotHandle.calculateDotProduct3D(this->pos, this->up);
mat.mat[2][3] = dotHandle.calculateDotProduct3D(this->pos, this->forward);

Matrix matrixHandle;

this->view = matrixHandle.matrixMultiplacation(this->view, mat);
}

Rotation:

void Camera::checkForRotation(Keybindings& keybindHandle, Window& window, Settings& settings, dt::vec3uis playerPos) {
if (settings.getCameraMode() == 0) {
if (keybindHandle.mouseMiddleClick) {
int mouseDistX = keybindHandle.mousePos.x - keybindHandle.prevMousePos.x;
int mouseDistY = keybindHandle.mousePos.y - keybindHandle.prevMousePos.y;

this->rot.x += mouseDistY * this->thirdPersonSpeed;
this->rot.y += mouseDistX * this->thirdPersonSpeed;
}
}
else if (settings.getCameraMode() == 1) {
if (keybindHandle.mouseMoveFlag) {
//rotation on y axis
if (keybindHandle.mousePos.x != window.getDimentions().x / 2) {
if (keybindHandle.mousePos.x < window.getDimentions().x / 2) {
int dist = (window.getDimentions().x / 2) - keybindHandle.mousePos.x;
this->rot.y += this->mouseSensitivity * dist;
}
else if (keybindHandle.mousePos.x > window.getDimentions().x / 2) {
int dist = keybindHandle.mousePos.x - (window.getDimentions().x / 2);
this->rot.y -= this->mouseSensitivity * dist;
}
}

//rotation on x axis
if (keybindHandle.mousePos.y != window.getDimentions().y / 2) {
if (keybindHandle.mousePos.y > window.getDimentions().y / 2) {
int dist = keybindHandle.mousePos.y - (window.getDimentions().y / 2);
this->rot.x -= this->mouseSensitivity * dist;
}
else if (keybindHandle.mousePos.y < window.getDimentions().y / 2) {
int dist = (window.getDimentions().y / 2) - keybindHandle.mousePos.y;
this->rot.x += this->mouseSensitivity * dist;
}
}
}
}

Normalise normHandle;

dt::mat4 mat;

mat.mat[0][0] = cos(-this->rot.y * (M_PI / 180)) * cos(-this->rot.z * (M_PI / 180));
mat.mat[1][0] = sin(-this->rot.x * (M_PI / 180)) * sin(-this->rot.y * (M_PI / 180)) - cos(-this->rot.x * (M_PI / 180)) * sin(-this->rot.z * (M_PI / 180));
mat.mat[2][0] = cos(-this->rot.x * (M_PI / 180)) * sin(-this->rot.x * (M_PI / 180)) * cos(-this->rot.z * (M_PI / 180)) + sin(-this->rot.x * (M_PI / 180)) * sin(-this->rot.z * (M_PI / 180));

mat.mat[0][1] = cos(-this->rot.y * (M_PI / 180)) * sin(-this->rot.z * (M_PI / 180));
mat.mat[1][1] = sin(-this->rot.x * (M_PI / 180)) * sin(-this->rot.y * (M_PI / 180)) * sin(-this->rot.z * (M_PI / 180)) + cos(-this->rot.x * (M_PI / 180)) * cos(-this->rot.z * (M_PI / 180));
mat.mat[2][1] = cos(-this->rot.x * (M_PI / 180)) * sin(-this->rot.y * (M_PI / 180)) * sin(-this->rot.z * (M_PI / 180)) - sin(-this->rot.x * (M_PI / 180)) * cos(-this->rot.z * (M_PI / 180));

mat.mat[0][2] = -sin(-this->rot.y * (M_PI / 180));
mat.mat[1][2] = sin(-this->rot.x * (M_PI / 180)) * cos(-this->rot.y * (M_PI / 180));
mat.mat[2][2] = cos(-this->rot.x * (M_PI / 180)) * cos(-this->rot.y * (M_PI / 180));

Matrix matrixHandle;
this->rotation = dt::mat4();

this->rotation = matrixHandle.matrixMultiplacation(this->rotation, mat);
}

Translate:

void Camera::checkForTranslation(Keybindings& keybindings, float farPlane,Settings& settings, Tick& tick, dt::vec3uis playerPos,Window& window) {

Cross crossHandle; Normalise normHandle; Dot dotHandle;

this->target.x = cos(this->rot.x * (M_PI / 180)) * sin(this->rot.y * (M_PI / 180));
this->target.y = sin(this->rot.x * (M_PI / 180));
this->target.z = cos(this->rot.x * (M_PI / 180)) * cos(this->rot.y * (M_PI / 180));

dt::vec3f p = normHandle.normalize3D(this->pos, farPlane);

this->forward.x = (p.x - this->target.x);
this->forward.y = (p.y - this->target.y);
this->forward.z = (p.z - this->target.z);


dt::vec3f right = dt::vec3f(0, 0, 0);
right.x = sin((this->rot.y * (M_PI / 180)) - M_PI / 2.0);
right.y = 0;
right.z = cos((this->rot.y * (M_PI / 180)) - M_PI / 2.0);


this->up = crossHandle.findCrossProduct(this->forward, right);

if (settings.getCameraMode() == 0) {
if (keybindings.mouseScroll != 0) {
if (keybindings.mouseScroll > 0) { //forwards
this->thirdPersonMovementDirection = 0;
}
else if (keybindings.mouseScroll < 0) {
this->thirdPersonMovementDirection = 1;
}

this->thirdPersonCameraMoving = true;
this->thirdPersonCameraMovementCharge = abs(keybindings.mouseScroll);
keybindings.mouseScroll = 0;
}
if (this->thirdPersonCameraMoving) {
if (tick.getThirtyTwoTickTriggerd()) {
if (this->thirdPersonMovementDirection == 0) { //forwards
this->pos.x -= this->forward.x * this->thirdPersonScrollSpeed;
this->pos.y -= this->forward.y * this->thirdPersonScrollSpeed;
this->pos.z -= this->forward.z * this->thirdPersonScrollSpeed;
}
else if (this->thirdPersonMovementDirection == 1) { //backwards
this->pos.x += this->forward.x * this->thirdPersonScrollSpeed;
this->pos.y += this->forward.y * this->thirdPersonScrollSpeed;
this->pos.z += this->forward.z * this->thirdPersonScrollSpeed;
}

//speed
this->thirdPersonScrollSpeed += 0.005;
this->thirdPersonCameraMovementCharge -= thirdPersonScrollSpeed;

if (this->thirdPersonCameraMovementCharge <= 0) {
this->thirdPersonCameraMoving = false;
this->thirdPersonScrollSpeed = 0.1;
}
}
}
}
else if (settings.getCameraMode() == 1) {
if (keybindings.forwardFlag) {
this->pos.x -= this->forward.x * this->firstPersonSpeed;
this->pos.y -= this->forward.y * this->firstPersonSpeed;
this->pos.z -= this->forward.z * this->firstPersonSpeed;
}

if (keybindings.backwardFlag) {
this->pos.x += this->forward.x * this->firstPersonSpeed;
this->pos.y += this->forward.y * this->firstPersonSpeed;
this->pos.z += this->forward.z * this->firstPersonSpeed;
}

if (keybindings.leftFlag) {
this->pos.x -= right.x * this->firstPersonSpeed;
this->pos.y -= right.y * this->firstPersonSpeed;
this->pos.z -= right.z * this->firstPersonSpeed;
}

if (keybindings.rightFlag) {
this->pos.x += right.x * this->firstPersonSpeed;
this->pos.y += right.y * this->firstPersonSpeed;
this->pos.z += right.z * this->firstPersonSpeed;
}
}

dt::mat4 mat;
mat.mat[0][0] = right.x;
mat.mat[0][1] = right.y;
mat.mat[0][2] = right.z;

mat.mat[1][0] = this->up.x;
mat.mat[1][1] = this->up.y;
mat.mat[1][2] = this->up.z;

mat.mat[2][0] = -this->forward.x;
mat.mat[2][1] = -this->forward.y;
mat.mat[2][2] = -this->forward.z;

mat.mat[0][3] = -dotHandle.calculateDotProduct3D(this->pos, right);
mat.mat[1][3] = -dotHandle.calculateDotProduct3D(this->pos, this->up);
mat.mat[2][3] = dotHandle.calculateDotProduct3D(this->pos, this->forward);

Matrix matrixHandle;

this->view = matrixHandle.matrixMultiplacation(this->view, mat);
}
3 Comments
2024/12/01
13:56 UTC

5

Rotate camera to look at point

I am trying to create something like glm::lookAt without using it because I want to understand how it works.

I want to use matrices and have tried googling around but cant find anything that helps.

I am not sure how to do the rotation towards the point.

Here is what I have so far:

void Camera::lookAtPoint(dt::vec3f targetPoint) {

Cross crossHandle; Normalise normHandle; Dot dotHandle;
this->target.x = cos(this->rot.x * (M_PI / 180)) * sin(this->rot.y * (M_PI / 180));
this->target.y = sin(this->rot.x * (M_PI / 180));
this->target.z = cos(this->rot.x * (M_PI / 180)) * cos(this->rot.y * (M_PI / 180));

dt::vec3f p = normHandle.normalize3D(this->pos, this->depthBounds.y);
dt::vec3f t = normHandle.normalize3D(targetPoint, this->depthBounds.y);

this->forward.x = (p.x - t.x);
this->forward.y = (p.y - t.y);
this->forward.z = (p.z - t.z);

dt::vec3f right = dt::vec3f(0, 0, 0);
right.x = sin((this->rot.y * (M_PI / 180)) - M_PI / 2.0);
right.y = 0;
right.z = cos((this->rot.y * (M_PI / 180)) - M_PI / 2.0);

this->up = crossHandle.findCrossProduct(this->forward, right);

dt::mat4 mat;
mat.mat[0][0] = right.x;
mat.mat[0][1] = right.y;
mat.mat[0][2] = right.z;

mat.mat[1][0] = this->up.x;
mat.mat[1][1] = this->up.y;
mat.mat[1][2] = this->up.z;

mat.mat[2][0] = -this->forward.x;
mat.mat[2][1] = -this->forward.y;
mat.mat[2][2] = -this->forward.z;

mat.mat[0][3] = -dotHandle.calculateDotProduct3D(this->pos, right);
mat.mat[1][3] = -dotHandle.calculateDotProduct3D(this->pos, this->up);
mat.mat[2][3] = dotHandle.calculateDotProduct3D(this->pos, this->forward);

Matrix matrixHandle;

this->view = matrixHandle.matrixMultiplacation(this->view, mat);
}
2 Comments
2024/11/30
12:03 UTC

2

glBlitFramebuffer for layered texture FBOs

How can I blit color or depth attachments of type GL_TEXTURE_2D_MULTISAMPLE_ARRAY with opengl. I have tried the following but gives error that there are binding errors, frame buffer binding not complete (during initialization there were no binding errors)

glBindFramebuffer(GL_READ_FRAMEBUFFER, gBufferMSAA);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, MSAAFramebuffer);

for (int layer = 0; layer < 2; ++layer) {
	glFramebufferTexture3D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE_ARRAY, depthTextureArrayMS, 0, layer);
	glFramebufferTexture3D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE_ARRAY, depthTextureMS, 0, layer);
	glBlitFramebuffer(0, 0, renderWidth, renderHeight, 0, 0, renderWidth, renderHeight,	GL_DEPTH_BUFFER_BIT, GL_NEAREST);  
}
0 Comments
2024/11/30
10:25 UTC

11

3D Mapping project: Lighting

I added some lighting to my 3D mapping project. Found a cool feature where I can create a 2D plane but calculate lighting as if it were in 3D. Provides a cool graphic resembling a satellite image.

First image is 2D, and the second is in 3D, both with lighting applied.

2D representation

3D representation

3 Comments
2024/11/30
07:15 UTC

1

LearnOpengl PointLight Shadow issue

New fish at OpenGL, I'm reading LearnOpenGL, and i try to implement the point Light shadow parts in my code, i already have Directional light shadow in the scene. Now i add the point Light shadow after render Directional shadow map, i render the point light depth to a 6 way CubeMap, but i got a whole white cubemap, so i did't get the object shadow at last. I check it twice, can some one help me?

main code:

while loop {

glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// 0. render  directionnal depth of scene to texture (from light's perspective)
// --------------------------------------------------------------
glm::mat4 lightProjection, lightView;
glm::mat4 lightSpaceMatrix;
float near_plane = 1.0f, far_plane = 7.5f;
lightProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane);
lightView = glm::lookAt(lightPos, glm::vec3(0.0f), glm::vec3(0.0, 1.0, 0.0));
lightSpaceMatrix = lightProjection * lightView;
// render scene from light's point of view
simpleDepthShader.use();
simpleDepthShader.setMat4("lightSpaceMatrix", lightSpaceMatrix);

glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
glClear(GL_DEPTH_BUFFER_BIT);
renderScene(simpleDepthShader);
glBindFramebuffer(GL_FRAMEBUFFER, 0);

// 1. Create depth cubemap transformation matrices
GLfloat aspect = (GLfloat)SHADOW_WIDTH / (GLfloat)SHADOW_HEIGHT;
GLfloat near = 1.0f;
GLfloat far = 25.0f;
glm::mat4 shadowProj = glm::perspective(90.0f, aspect, near, far);
std::vector<glm::mat4> shadowTransforms;
shadowTransforms.push_back(shadowProj * glm::lookAt(pointLight_pos, pointLight_pos + glm::vec3(1.0, 0.0, 0.0), glm::vec3(0.0, -1.0, 0.0)));
shadowTransforms.push_back(shadowProj * glm::lookAt(pointLight_pos, pointLight_pos + glm::vec3(-1.0, 0.0, 0.0), glm::vec3(0.0, -1.0, 0.0)));
shadowTransforms.push_back(shadowProj * glm::lookAt(pointLight_pos, pointLight_pos + glm::vec3(0.0, 1.0, 0.0), glm::vec3(0.0, 0.0, 1.0)));
shadowTransforms.push_back(shadowProj * glm::lookAt(pointLight_pos, pointLight_pos + glm::vec3(0.0, -1.0, 0.0), glm::vec3(0.0, 0.0, -1.0)));
shadowTransforms.push_back(shadowProj * glm::lookAt(pointLight_pos, pointLight_pos + glm::vec3(0.0, 0.0, 1.0), glm::vec3(0.0, -1.0, 0.0)));
shadowTransforms.push_back(shadowProj * glm::lookAt(pointLight_pos, pointLight_pos + glm::vec3(0.0, 0.0, -1.0), glm::vec3(0.0, -1.0, 0.0)));

// 2 : render point light shader
// --------------------------------------------------------------
pointLightShader.use();
for (GLuint i = 0; i < 6; ++i)
glUniformMatrix4fv(glGetUniformLocation(pointLightShader.ID, ("shadowMatrices[" + std::to_string(i) + "]").c_str()), 1, GL_FALSE, glm::value_ptr(shadowTransforms[i]));
pointLightShader.setVec3("lightPos", pointLight_pos);
pointLightShader.setFloat("far_plane", far);
glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
glBindFramebuffer(GL_FRAMEBUFFER, depthCubeMapFBO);
glClear(GL_DEPTH_BUFFER_BIT);
renderScene(pointLightShader);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
std::cout << "Cubemap FBO not complete!" << std::endl;
}

glBindFramebuffer(GL_FRAMEBUFFER, 0);

// reset viewport
glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// 3. render scene as normal using the generated depth/shadow map  
// --------------------------------------------------------------
shadowMapShader.use();
glm::mat4 projection = glm::perspective(glm::radians(camera.Fov), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
glm::mat4 view = camera.GetViewMatrix();
shadowMapShader.setMat4("projection", projection);
shadowMapShader.setMat4("view", view);
// set light uniforms
shadowMapShader.setVec3("viewPos", camera.Position);
shadowMapShader.setVec3("lightPos", lightPos);
shadowMapShader.setMat4("lightSpaceMatrix", lightSpaceMatrix);
shadowMapShader.setVec3("pointLights[0].position", pointLight_pos);
shadowMapShader.setVec3("pointLights[0].ambient", glm::vec3(0.05f, 0.05f, 0.05f));
shadowMapShader.setVec3("pointLights[0].diffuse", glm::vec3(0.8f, 0.8f, 0.8f));
shadowMapShader.setFloat("pointLights[0].intensity", p0_Intensity);
shadowMapShader.setVec3("pointLights[0].specular", glm::vec3(1.0f, 1.0f, 1.0f));
shadowMapShader.setFloat("pointLights[0].constant", 1.0f);
shadowMapShader.setFloat("pointLights[0].linear", 0.09f);
shadowMapShader.setFloat("pointLights[0].quadratic", 0.032f);

shadowMapShader.setFloat("far_plane", far);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, woodTexture);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, woodNormolTexture);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, depthMap);
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_CUBE_MAP, depthCubeMap);
renderScene(shadowMapShader);

}



shadowmap.fs

float PointShadowCalculation(PointLight light, vec3 fragPos)
{
    // Get vector between fragment position and light position
    vec3 fragToLight = fragPos - light.position;
    // Use the fragment to light vector to sample from the depth map    
    float closestDepth = texture(depthCubeMap, fragToLight).r;
    // It is currently in linear range between [0,1]. Let's re-transform it back to original depth value
    closestDepth *= far_plane;
    // Now get current linear depth as the length between the fragment and light position
    float currentDepth = length(fragToLight);
    // Now test for shadows
    float bias = 0.05; // We use a much larger bias since depth is now in [near_plane, far_plane] range
    float shadow = currentDepth -  bias > closestDepth ? 1.0 : 0.0;

    return shadow;
}

void main()
{           
    vec3 color = texture(diffuseTexture, fs_in.TexCoords).rgb;
    //vec3 normal = texture(normalTexture, fs_in.TexCoords).rgb;
    //normal = normalize(normal);
    vec3 normal = normalize(fs_in.Normal);
    vec3 lightColor = vec3(0.3);
    // ambient
    vec3 ambient = 0.3 * lightColor;
    // diffuse
    vec3 lightDir = normalize(lightPos - fs_in.FragPos);
    float diff = max(dot(lightDir, normal), 0.0);
    vec3 diffuse = diff * lightColor;
    // specular
    vec3 viewDir = normalize(viewPos - fs_in.FragPos);
    vec3 reflectDir = reflect(-lightDir, normal);
    float spec = 0.0;
    vec3 halfwayDir = normalize(lightDir + viewDir);  
    spec = pow(max(dot(normal, halfwayDir), 0.0), 64.0);
    vec3 specular = spec * lightColor;    
    // calculate shadow
    // float shadow = ShadowCalculation(fs_in.FragPosLightSpace); 
//here render the cubemap depth 
    float pshadow = PointShadowCalculation(pointLights[0], fs_in.FragPos);
    vec3 lighting = (ambient + (1.0 - pshadow) * (diffuse + specular)) * color;  
       
    // Point Light
    vec3 result = vec3(0.0);
    for(int i = 0; i < NR_POINT_LIGHTS; i++)
        result = CalcPointLight(pointLights[i], normal, fs_in.FragPos, viewDir);    

    FragColor = vec4(result + lighting, 1.0);
}

And the cubemap shader vs, fs, gs are same as LearnOpenGL web.

https://learnopengl.com/code_viewer_gh.php?code=src/5.advanced_lighting/3.2.2.point_shadows_soft/3.2.2.point_shadows_depth.vs

https://learnopengl.com/code_viewer_gh.php?code=src/5.advanced_lighting/3.2.2.point_shadows_soft/3.2.2.point_shadows_depth.fs

https://learnopengl.com/code_viewer_gh.php?code=src/5.advanced_lighting/3.2.2.point_shadows_soft/3.2.2.point_shadows_depth.gs

6 Comments
2024/11/29
07:52 UTC

7

Opaque faces sometimes not rendering when behind transparent object? (OpenGL 4.5)

12 Comments
2024/11/28
17:51 UTC

5

What is the equivalent of an OpengGL VAO in Direct3d, if any?

Direct3d dev here trying to learn OpenGL for cross-platform development. It has been a few months since I last did GL, but I plan on getting back to it, so please excuse me if I am remembering it wrong.

Since I’ve done DirectX programming most of my time programming, I cannot wrap my head around GL VAOs that easily as of now. For those who have done both, do they have a equivalent in Direct3d?

For example, I figured out that I would need a single VAO for each buffer I create, or otherwise it wouldn’t render. In Direct3d all we would need is a single buffer object, a bind, and a draw call.

They do seem a little similar to input layouts, though. We use those in Direct3d in order to specify what data structure the vertex shader expects, which resembles the vertex attrib functions a quite a little.

Although I am not aware if they have a direct (pun not intended) equivalent, I still wanted to ask.

10 Comments
2024/11/28
11:20 UTC

24

Why khronos. Just why...

So as we all know the last opengl version we saw was 4.6 back in 2017 and we will probably not see opengl 4.7. The successor of opengl is "supposed" to be vulkan. I tried vulkan but it didn't work because I had missing extensions or drivers I don't really know myself. People say that if more and more people are using vulkan it's because it's much faster and has more low level control on the gpu. I think the reality is that people that are using vulkan are people who decided to stop using opengl since there will be no more updates. That was literally the reason I wanted to learn vulkan at first but looks like i'll have to stay with opengl (which i'm not complaining about). Khronos instead of making a whole new api they could've make a big update with the 5.x releases (like they did back when there was the switch from 2.x releases to 3.x , 3.x releases brought huge new updates which I think most of you guys in this sub know that i'm talking about). Also the lack of hardware compatibility with older GPUs in vulkan is still a big problem. Pretty strange move that after all of these decades where opengl was around (since 1992 to be exact) they decided to just give up the project and start something new. So I know that opengl will not just disappear and it's still going to be around for a few years but still I think khronos had better choices than giving up opengl and make a new api.

41 Comments
2024/11/27
21:13 UTC

2

Instanced sprites not rendering

Hello! I'm trying to render some billboards using instanced rendering. But for some reason, the sprites just aren't rendering at all. I am using the GLM library and in my renderer, this is how I initialize the VAO and VBO:

float vertices[] = {
    // positions         // texture coords
    0.5f,  0.5f,  0.0f, 1.0f, 1.0f, // top right
    -0.5f, 0.5f,  0.0f, 0.0f, 1.0f, // top left
    -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, // bottom left
    0.5f,  -0.5f, 0.0f, 1.0f, 0.0f  // bottom right
};

unsigned int indices[] = {
    0, 1, 3, // first triangle
    1, 2, 3  // second triangle
};

glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);

glBindVertexArray(VAO);

glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

// Position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// Texture attribute
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);

std::vector<glm::mat4> particleMatrices;

glGenBuffers(1, &instancedVBO);

// Reserve space for instance transformation matrices
glBindBuffer(GL_ARRAY_BUFFER, instancedVBO);
glBufferData(GL_ARRAY_BUFFER, MAX_PARTICLES * sizeof(glm::mat4), nullptr, GL_DYNAMIC_DRAW);

// Enable instanced attributes
glBindVertexArray(VAO);
for (int i = 0; i < 4; i++)
{
    glVertexAttribPointer(2 + i, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(i * sizeof(glm::vec4)));
    glEnableVertexAttribArray(2 + i);
    glVertexAttribDivisor(2 + i, 1); // Instance divisor for instancing
}

And this is how I render them every frame:

particleMatrices.clear();
for (int i = 0; i < par.particles.size(); ++i)
{
    particleMatrices.push_back(glm::mat4(1.0f));
    particleMatrices[i] =
        glm::translate(particleMatrices[i], glm::vec3(par.particles[i].position.x, par.particles[i].position.y,
                                                      par.particles[i].position.z));
    glm::mat4 rotationCancel = glm::transpose(glm::mat3(view));
    particleMatrices[i] = particleMatrices[i] * glm::mat4(rotationCancel);
    particleMatrices[i] =
        glm::scale(particleMatrices[i], glm::vec3(par.particles[i].size.x, par.particles[i].size.y, 1.0f));
}

// Update instance transformation data
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, instancedVBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, particleMatrices.size() * sizeof(glm::mat4), particleMatrices.data());

parShader.use();
parShader.setTexture2D("texture1", par.texture, 0);

// Setting all the uniforms.
parShader.setMat4("view", view);
parShader.setMat4("projection", projection);
parShader.setVec4("ourColor", glm::vec4(1.0f));

glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0, par.particles.size());

I've debug printed the position, size and matrices of the particles and they seem just about fine. The fragment shader is very simple, and this is the vertex shader if you're wondering:

#version 330 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec2 aTexCoord;
layout(location = 2) in mat4 aInstanceMatrix;

out vec2 TexCoord;
out vec3 FragPos;

uniform mat4 view;
uniform mat4 projection;

void main()
{
    FragPos = vec3(aInstanceMatrix * vec4(aPos, 1.0)); // Transform vertex to world space
    TexCoord = aTexCoord;
    gl_Position = projection * view * vec4(FragPos, 1.0);
}

I've gone in RenderDoc and tried to debug and it seems that the instanced draw calls draw only one particle, and then the particle dissapears in the Colour Pass #1 (1 targets + depth)

1 Comment
2024/11/27
19:24 UTC

1

glMultiDrawElementsIndirect crashes only on integrated gpus with GL_INVALID_OPERATION

Title self explanatory. I'm creating an indirect buffer, and filling it with the proper data, then sending that data to the GPU before making the draw call. Works (almost) perfectly fine on my desktop PC, and other's desktop PC's, but crashes on every Integrated GPU such as a laptop we've tried it on. I'm very new to OGL so im not even sure where to begin. I updated my graphics drivers, tried organizing my data differently, used a debug message callback, looked at render doc, nothing is giving me any hints. I've asked around in a few Discord servers and nobody's been able to figure it out. If it helps, I'm using glNamedBufferSubData to update my vertex buffer in chunks, where each 'chunk' corresponds to an indirect call. My program is written in Jai. Id imagine its too much code to post here, so if itd be more helpful to see it let me know and I can link a repo. Thank you all in advance.

6 Comments
2024/11/26
03:08 UTC

18

Your Opinion: Unknown post processing effects, that add A LOT

What post processing effects do you consider unknown, that enhance visual quality by a lot?

4 Comments
2024/11/25
11:01 UTC

10

UI, UI, UI

UI is such a big issue. In one case, it's something we all know and have opinions about, in another case, we just want to plow through it and get to the game itself.

In my game engine, written in OpenGL but no longer in a workable state, existing at the repos https://github.com/LAGameStudio/apolune and at https://github.com/LAGameStudio/ATE there are multiple UI approaches. It was a topic I kept coming back to again and again because it was hard to keep in a box.

My engine uses a "full screen surface" or an "application surface", using double buffering. The classic "Game engine" style window. Mine was not easily resizable though once the app was running. You specified "Fullscreen" and "display size" as command line parameters, or it detected your main monitor's dimensions and tried to position itself as a fullscreen application on that monitor.

The first UI system I made grew over time to be rather complex, but it is the most flexible. Over time it became apparent that I needed to decouple UI from the concept of a Window. It was a class, GLWindow, working inside a GLWindowManager class that was a global singleton. This is the foundational class for my engine. The thing is though, the "Window" concept broke down over time. A GLWindow was just a bit of rendering, so it could render a 3D scene, multiple 3D scenes, a 2D HUD, all of those things, only one of those things, or something else entirely, or maybe nothing at all (a "background" task). I realized I needed to create widgets that could be reused and not call them GLWindows.

The second modular UI I made for the engine was fairly complicated. It involved a "Widget" (class Proce55or) being added to a "Widget Collection" (class Proce55ors) that is hooked to a "Window" (class GLWindow) -- with Proce55or, you could make anything: a button, a widget, a game entity, a subview, a slider, whatever. In fact, a Proce55or could have a derived class that enabled a collection of Proce55ors.

With that I created some "basic UI" features. Buttons that were animated, sliders, text boxes (which requires some special stuff), and the code looked like:

class NewGameButton : public fx_Button { public:
 void OnInit() {
  Extents( 5, 10, 200, 100 );  /* x/y/w/h .. could be calculated to be "responsive" ..etc */
 }
 void OnButtonPressed() {
  /* do something */
 }
};
class MyWindow : public GLWindow { public:
  Proce55ors processors;
 void OnLoad() {
  process.Add(new NewGameButton);
   /* ... repeat for every widget ... */
 }
 void Between() { proce55ors.Between(); }
 void Render() { proce55ors.Render(); }
 void OnMouseMoved() { proce55ors.MouseMoved(); } /* to interact with the UI elements */
 void OnMouseLeft() { proce55ors.MouseLeft(); } /* etc.. a rudimentary form of messaging */
};
   

The pattern used classic polymorphism features of C++.
Create a child NewGameButton of fx_Button (a child of Proce55or that contains the common input and drawing routines as a partially abstract class with some virtuals for events), adding the customization and logic there to be inserted into a Proce55ors collection running in a GLWindow child.. but it required a lot of forward declarations of the window it was going to interact with, or it required new systems to be added to GLWindowManager so you could refer to windows by a name, instead of direct pointers, or it required the button to manipulate at least one forward declared management object that would be a part of your MyWindow to manage whatever state your buttons, sliders, etc were going to interface with...

This became cumbersome. I needed something quick-and-dirty so I could make some quick utilities similar to the way imgui worked. It had buttons and sliders and other widgets. I called this "FastGUI" and it was a global singleton ("fast") that contained a bunch of useful utility functions. These were more like an imgui ... it looked like this:

class MyWindow : public GLWindow { public:
 void Render() {
   if ( fast.button( this->x+5, this->y+10, 200, 100, "New Game") ) {  /* the window's top left + button location desired */
    windows.Add(new MyNewGameWindow());
    deleteMe=true; /* deferred delete */
    return; /* stop rendering and quickly move to next frame */
   }
 }
};

The biggest issue was, while I found it "neat" to hardcode the position on the screen, it wasn't practical.

Most UIs in OpenGL have an abstraction .. mine was pixel perfect but yours could be a ratio of the screen. I tried that for a while, but that became very confusing. For example you could change the size of a GLWindow by calling Extents( 0.25, 0.25, 0.5, 0.5 ); this would make the GLWindow a centered box the size of 1/4th the screen area. This was practical, but confusing, etc etc. A lot of your time was spent recompiling, checking it onscreen, etc.

Eventually I combined FastGUI with ideas from Proce55ors. Since it took so much time to organize the location of buttons, for more utilitarian things I began to explore using algorithmic placement methods. For example, using a bin packing algorithm to place buttons or groups of buttons and other widgets. I added the ability for a window to open a subwindow that drew a line from the source window to the subwindow, and an infintely scrolling work area. The UI became more and more complicated, yet in some ways easier to deploy new parts. This was the VirtualWindow and related classes.

5 Comments
2024/11/25
01:57 UTC

0

how do i fix black screen error in opengl?

Im getting a black screen after i compile a code in open gl, the same code was working a month ago, ive tried different codes i found online and i have the same result i looked for solutions online but i didnt found anything ,i tried to change the settings on my terminal and on codeblocks and still nothing

heres the code:

#include <gl/glut.h>

#include <stdio.h>

void display()

{

glClearColor(1,1,1,1);

glClear(GL_COLOR_BUFFER_BIT);

printf("El Zabon");

glColor3f(0,1,0);

glRectf(0,0,30,100);

glColor3f(1,0,0);

glRectf(100,100,70,0);

glEnd();

glFlush();

}

int main(int argc, char** argv)

{

printf("El Zabon");

glutInit(&argc,argv);

glutInitWindowPosition(50,50);

glutInitWindowSize(640,480);

glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);

glutCreateWindow("Ιταλια");

glMatrixMode(GL_PROJECTION);

gluOrtho2D(0,100,0,100);

glutDisplayFunc(display);

glutMainLoop();

return 0;

}

6 Comments
2024/11/24
22:48 UTC

3

Thousands of arcs and bezier curves help

Here is what I am trying to recreate:

https://preview.redd.it/202np6ujbx2e1.png?width=2750&format=png&auto=webp&s=c633b54acba06038fe14cdfb25495585f095b507

Basically all the connections between nodes. There seems like quite a few variations. Back in their first game (path of exile), they used only arcs, now they seem to have added reversed arcs and possibly bezier curves? Please correct me if I am wrong.

The main question is, what would be the best way to achieve this? I'd imagine a single system is best as to not complicate things? Would that be bezier curves? Any help on this would be really appreciated, I feel completely lost atm

6 Comments
2024/11/24
22:25 UTC

5

Whats your goto approach for creating an ingame-ui system?

Would like to be inspired by you guys :)

12 Comments
2024/11/24
22:16 UTC

5

Any use for pre-2.0 renderers? Part 2

https://preview.redd.it/bi7lxzwg5y2e1.png?width=813&format=png&auto=webp&s=3ae47d86414786e8e2c644936a53a02b7b4add7e

https://reddit.com/link/1gz33cn/video/y6iw9cmeax2e1/player

(previous post)
small progress report, it's something i really wanted to figure out without shaders: shadowmaps!

this uses features from ARB_depth_texture and ARB_shadow, I fell short on the aesthetics of the projected shadows because it turns out i was going to use EXT_convolution to blur the texture on the GPU but it turns out this extension is simply non-existent on my RTX, so no way of testing it... I'd have to do it on the CPU instead lol, because no shaders allowed still...

another more subtle change: the texture logic was now translated to combiners, including the use of ARB_texture_env_dot3 for the normal map, it's not as noticeable as i would like but it seems to be the full extent of how it works.

i switched up the scene in the video to show the difference!

EDIT: just noticed now i forgot to clamp the bloom overlay texture, oops!

5 Comments
2024/11/24
22:13 UTC

2

SDL ttf with opengl

Is there any documentation on how to use SDL ttf with opengl ? I searched on the internet but it was posts from 13 years ago or more. These guys used the opengl versions with glBegin and glEnd. I want the versions with VAO, VBO and EBO (so from 3.0 - 4.6 I think). Thanks in advance.

3 Comments
2024/11/24
21:52 UTC

6

SSAO in forward rendering: Apply in forward pass, or in post processing?

Hey guys, i was wondering what the correct approach to SSAO in forward rendering is:

a)

1. Forward pass

2. SSAO generation

3. Darken forward pass result according to SSAO in another pass

or...

b)

1. SSAO generation

2. Forward pass with samples from SSAO

Consider i am doing a gemoetry pre pass beforehand in any way. Since SSAO is a screenspace effect i thought a) was correct, but as the skybox is black from my SSAO generation that doesn't work as expected.

Thanks!

10 Comments
2024/11/24
20:59 UTC

3

I have not made a devlog in awhile, thought I would ...only a tiny bit embarrassing but maybe a little enjoyable to some!

0 Comments
2024/11/24
20:31 UTC

2

CLION GLFW Illegal instruction

Hey everyone, I've been spending a good bit converting a visual studio project over to Cmake for various reasons (Using CLION as the new IDE) and though I've gotten it to run finally, I have a strange bug breaking my program.

When doing glfwMakeCurrentContext(window), My program crashes with the exit code -1073741795 (0xC000001D), and in debug it shows that this function is a SIGILL (Illegal instruction).

The GLFW relevant code is below, ran in order-

Graphics system initialization:

bool GraphicsSystem::Init()
{
    if (glfwInit() == GLFW_FALSE)
    {
       glfwTerminate();
       return false;
    }

    if (!_win.InitWindow(_width, _height, _windowName.data()))
    {
       printf("GLFW failed to create window");
       return false;
    }
    testCam = LILLIS::Camera(glm::vec2(0, 0), _width, _height);
    glfwSetErrorCallback(error_callback);

    // load shaders
    ResourceManager::
loadDefaultPipeline
();
    // configure shaders
    ResourceManager::
GetShader
("Default").Use().SetInteger("image", 0);
    ResourceManager::
GetShader
("Default").SetMatrix4("projection", testCam.projectionMatrix());
    // set render-specific controls
    testSpr = DBG_NEW SpriteRenderer(ResourceManager::
GetShader
("Default"));
    // load textures
    //For the love of god, move the sprite holder here.
    ResourceManager::
LoadTexture
("Test.png", true, "face");
    ResourceManager::
LoadTexture
("Angry.png", true, "enemy");
    ResourceManager::
LoadTexture
("Player1.png", true, "p1");
    ResourceManager::
LoadTexture
("Player2.png", true, "p2");
    ResourceManager::
LoadTexture
("WinFlag.png", true, "goal");
    return true;

Window wrapper initialization (Where the error is happening)

bool InitWindow(unsigned int _width, unsigned int _height, const char* _name)
{
    window = glfwCreateWindow(_width, _height, _name, NULL, NULL);
    if (window == NULL)
    {
       glfwTerminate();
       return false;
    }
    glfwMakeContextCurrent(window);
}

I'm running this on a windows 10 machine with an intel CORE i7 8th gen, I was not encountering this error when this was a visual studio project running with a .sln file-

I can confirm that the code is running in the aforementioned order, and that the glfwMakeContextCurrent(window); is the exact line causing issue.

If more context is needed, all of the code is here https://github.com/Spegetemitbal/LillisEngine

Has anyone seen this before? Any idea what to do? Any advice would be greatly appreciated, I'm at my wit's end with refactoring this project lol

5 Comments
2024/11/24
19:22 UTC

11

How long would it take to understand and develope a 3D renderer in openGL?

I know all fundamentals. linear algebra, 3D graphics, c++ etc. I have lots of free time right now. How long would it take to develope a 3D renderer? Answer with time spent on learning and developing. Not time it takes with doing other things(sleeping, eating ....)

12 Comments
2024/11/24
16:34 UTC

11

Created a 2D GUI system in OpenGL for a game I'm working on

0 Comments
2024/11/23
21:49 UTC

Back To Top