Broken perspective projection matrix in OpenGL - c

I've been working on the transformations tutorial from open.gl and am having trouble making my perspective projection matrix work. The tutorial uses GLM, but I chose to roll my own matrix math functions to try and learn the math a little better. Everything compiles fine (gcc -Wall), and my rotation and lookat matrix functions are working perfectly, but my perspective projection matrix causes a black screen with no OpenGL errors.
The projection matrix is (I think) supposed to be
/ cot(fovy/2)/aspect 0.0 0.0 0.0 \
| 0.0 cot(fovy/2) 0.0 0.0 |
| 0.0 0.0 (zfar + znear)/(znear - zfar) -1.0 |
\ 0.0 0.0 (2 * zfar * znear)/(znear - zfar) 0.0 /
Interestingly, I can provide the intended effect with the matrix
/ cot(fovy/2)/aspect 0.0 0.0 0.0 \
| 0.0 cot(fovy/2) 0.0 0.0 |
| 0.0 0.0 (zfar + znear)/(znear - zfar) -1.0 |
\ 0.0 0.0 0.4 1.0 /
Here are the necessary source files. You'll need GLFW3 and SOIL to compile the code -- I've been using gcc -Wall -Werror -std=c99 -lGL -lGLEW -lglfw -lm -lSOIL transform.c -o transform. I've tried to provide shorter (non-compiling) versions of the source below in case there are any glaring errors.
transform.c:
#include <math.h>
#define M_PI (3.14159265358979323846)
#include <stdio.h>
#include <stdlib.h>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <SOIL/SOIL.h>
typedef struct mat4_t {
float arr[16];
} mat4_t;
typedef struct vec3_t {
float arr[3];
} vec3_t;
/* forward declarations... */
/* return a 4x4 'lookat' matrix to be multiplied by model space coords */
mat4_t mat4mklook(const vec3_t eye, const vec3_t center, const vec3_t up) {
/* check out the OpenGL gluLookAt documentation for an explanation */
vec3_t f = vec3norm(vec3sub(center, eye));
vec3_t up_ = vec3norm(up);
vec3_t s = vec3cross(f, up_);
vec3_t u = vec3cross(s, f);
return (mat4_t) { {
s.arr[0], s.arr[1], s.arr[2], 0.0f,
u.arr[0], u.arr[1], u.arr[2], 0.0f,
-f.arr[0], -f.arr[1], -f.arr[2], 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
} };
}
/* return a 4x4 persp. projection matrix to be multiplied by camera coords */
mat4_t mat4mkproj(const float fovy, const float aspect, const float znear, const float zfar) {
float f = 1 / tan(fovy / 2.0f);
return (mat4_t){ {
f/aspect, 0.0f, 0.0f, 0.0f,
0.0f, f, 0.0f, 0.0f,
0.0f, 0.0f, (zfar+znear)/(znear-zfar), (2*zfar*znear)/(znear-zfar),
0.0f, 0.0f, -1.0f, 0.0f
} };
}
/* returns a 4x4 rotation matrix of magnitude 'th' about unit vector 'axis' */
mat4_t mat4mkrot(const vec3_t axis, const float th) {
const float uX = axis.arr[0];
const float uY = axis.arr[1];
const float uZ = axis.arr[2];
const float sinth = sin(th);
const float costh = cos(th);
return (mat4_t) { {
costh+pow(uX,2)*(1-costh), uX*uY*(1-costh)-uZ*sinth, uX*uZ*(1-costh)+uY*sinth, 0.0,
uY*uX*(1-costh)+uZ*sinth, costh+pow(uY,2)*(1-costh), uY*uZ*(1-costh)-uX*sinth, 0.0,
uZ*uX*(1-costh)-uY*sinth, uZ*uY*(1-costh)+uX*sinth, costh+pow(uZ,2)*(1-costh), 0.0,
0.0, 0.0, 0.0, 1.0
} };
}
/* returns the product of matrices 'a' and 'b' */
mat4_t mat4mult(const mat4_t a, const mat4_t b) {
mat4_t result;
for(int i = 0; i < 16; ++i) {
result.arr[i] = 0.0f;
for(int j = 0; j < 4; ++j) {
result.arr[i] += a.arr[i / 4 + j] * b.arr[i % 4 + j * 4];
}
}
return result;
}
/* returns the cross product of vectors 'a' and 'b' */
vec3_t vec3cross(const vec3_t a, const vec3_t b) {
return (vec3_t){ {
a.arr[1] * b.arr[2] - a.arr[2] * b.arr[1],
a.arr[2] * b.arr[0] - a.arr[0] * b.arr[2],
a.arr[0] * b.arr[1] - a.arr[1] * b.arr[0]
} };
}
/* returns a unit vector derived from vector 'v' */
vec3_t vec3norm(const vec3_t a) {
vec3_t result;
float mag;
if((mag = sqrt(pow(a.arr[0], 2) + pow(a.arr[1], 2) + pow(a.arr[2], 2))) == 0.0f) {
result = (vec3_t) {{0}};
} else {
for(int i = 0; i < 3; ++i) {
result.arr[i] = a.arr[i] / mag;
}
}
return result;
}
/* return the vector difference 'a' - 'b' */
vec3_t vec3sub(const vec3_t a, const vec3_t b) {
vec3_t result;
for(int i = 0; i < 3; ++i) {
result.arr[i] = a.arr[i] - b.arr[i];
}
return result;
}
/* returns the dot product of vectors 'a' and 'b' */
float vec3dot(const vec3_t a, const vec3_t b) {
return a.arr[0] * b.arr[0] +
a.arr[1] * b.arr[1] +
a.arr[2] * b.arr[2];
}
GLfloat vertices[] = {
/* position texture */
-0.5f, 0.5f, 0.0f, 0.0f,
0.5f, 0.5f, 1.0f, 0.0f,
0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, 0.0f, 1.0f
};
GLuint elements[] = {
0, 1, 2,
2, 3, 0
};
int main() {
glfwInit();
/* context settings */
/* window & context creation */
GLFWwindow * const window = glfwCreateWindow(800, 600, "OpenGL", NULL, NULL);
glfwMakeContextCurrent(window);
/* glew initialization -- generates harmless error */
glewExperimental = GL_TRUE;
glewInit();
glGetError();
/* vertex setup */
/* shader setup */
/* vertex attribute setup */
/* texture setup */
GLint modeluni;
{ /* matrix uniform setup */
modeluni = glGetUniformLocation(shaderProgram, "model");
mat4_t viewmat = mat4mklook((vec3_t){{1.2f, 1.2f, 1.2f}}, (vec3_t){{0.0f, 0.0f, 0.0f}}, (vec3_t){{0.0f, 0.0f, 1.0f}});
GLint viewuni = glGetUniformLocation(shaderProgram, "view");
glUniformMatrix4fv(viewuni, 1, GL_TRUE, viewmat.arr);
mat4_t projmat = mat4mkproj(M_PI / 4.0f, 800.0f / 600.0f, 1.0f, 10.0f);
GLint projuni = glGetUniformLocation(shaderProgram, "proj");
glUniformMatrix4fv(projuni, 1, GL_TRUE, projmat.arr);
}
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
while(!glfwWindowShouldClose(window)) {
const GLuint error = glGetError();
if(error) {
fprintf(stderr, "%d\n", error);
}
glClear(GL_COLOR_BUFFER_BIT);
mat4_t modmat = mat4mkrot((vec3_t){{0.0f, 0.0f, 1.0f}}, (glfwGetTime() / 2.0) * M_PI);
glUniformMatrix4fv(modeluni, 1, GL_TRUE, modmat.arr);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glfwSwapBuffers(window);
glfwPollEvents();
}
/* delete opengl ids */
glfwTerminate();
return 0;
}
vert.glsl:
#version 330
in vec2 position;
in vec3 color;
in vec2 texcoord;
out vec3 Color;
out vec2 Texcoord;
uniform mat4 model;
uniform mat4 view;
uniform mat4 proj;
void main() {
Color = color;
Texcoord = texcoord;
gl_Position = proj * view * model * vec4(position.x, position.y, 0.0, 1.0);
}
frag.glsl:
#version 330
in vec3 Color;
in vec2 Texcoord;
out vec4 outColor;
uniform sampler2D texKitten;
uniform sampler2D texPuppy;
void main() {
vec4 colKitten = texture(texKitten, Texcoord);
vec4 colPuppy = texture(texPuppy, Texcoord);
outColor = mix(colKitten, colPuppy, 0.5);
}

Related

OpenGL ortho projection is broken

So I just added ortho projection to my rendering and everything stopped rendering... If I remove it, it works again. This is my matrix code:
#include <stdlib.h>
#include <stdlib.h>
#include <math.h>
matrix4x4 init_matrix4x4() {
matrix4x4 m = calloc(16, sizeof(float));
m[0] = 1; m[1] = 0; m[2] = 0; m[3] = 0;
m[4] = 0; m[5] = 1; m[6] = 0; m[7] = 0;
m[8] = 0; m[9] = 0; m[10] = 1; m[11] = 0;
m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1;
return m;
}
void translate_matrix4x4(matrix4x4* matrix, float x, float y, float z) {
matrix4x4 m = (*matrix);
m[12] = m[0] * x + m[4] * y + m[8] * z + m[12];
m[13] = m[1] * x + m[5] * y + m[9] * z + m[13];
m[14] = m[2] * x + m[6] * y + m[10] * z + m[14];
m[15] = m[3] * x + m[7] * y + m[11] * z + m[15];
}
void ortho_matrix4x4(matrix4x4* matrix, float left, float right, float bottom, float top, float near, float far) {
matrix4x4 m = (*matrix);
m[0] = 2 / (right-left);
m[1] = 0;
m[2] = 0;
m[3] = 0;
m[4] = 0;
m[5] = 2 / (top - bottom);
m[6] = 0;
m[7] = 0;
m[8] = 0;
m[9] = 0;
m[10] = 1 / (far - near);
m[11] = 0;
m[12] = (left + right) / (left - right);
m[13] = (top + bottom) / (bottom - top);
m[14] = near / (near - far);
m[15] = 1;
}
void mat4_identity(matrix4x4* matrix) {
matrix4x4 out = (*matrix);
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = 1;
out[6] = 0;
out[7] = 0;
out[8] = 0;
out[9] = 0;
out[10] = 1;
out[11] = 0;
out[12] = 0;
out[13] = 0;
out[14] = 0;
out[15] = 1;
}
void mat4_lookAtf(matrix4x4* matrix, float eye[3], float center[3], float up[3]) {
matrix4x4 out = (*matrix);
float x0, x1, x2, y0, y1, y2, z0, z1, z2, len,
eyex = eye[0],
eyey = eye[1],
eyez = eye[2],
upx = up[0],
upy = up[1],
upz = up[2],
centerx = center[0],
centery = center[1],
centerz = center[2];
if (fabs(eyex - centerx) < 0.000001 &&
fabs(eyey - centery) < 0.000001 &&
fabs(eyez - centerz) < 0.000001) {
mat4_identity(&out);
return;
}
z0 = eyex - centerx;
z1 = eyey - centery;
z2 = eyez - centerz;
len = 1 / sqrt/*f*/(z0 * z0 + z1 * z1 + z2 * z2);
z0 *= len;
z1 *= len;
z2 *= len;
x0 = upy * z2 - upz * z1;
x1 = upz * z0 - upx * z2;
x2 = upx * z1 - upy * z0;
len = sqrt(x0 * x0 + x1 * x1 + x2 * x2);
if (!len) {
x0 = 0;
x1 = 0;
x2 = 0;
} else {
len = 1 / len;
x0 *= len;
x1 *= len;
x2 *= len;
}
y0 = z1 * x2 - z2 * x1;
y1 = z2 * x0 - z0 * x2;
y2 = z0 * x1 - z1 * x0;
len = sqrt(y0 * y0 + y1 * y1 + y2 * y2);
if (!len) {
y0 = 0;
y1 = 0;
y2 = 0;
} else {
len = 1 / len;
y0 *= len;
y1 *= len;
y2 *= len;
}
out[0] = x0;
out[1] = y0;
out[2] = z0;
out[3] = 0;
out[4] = x1;
out[5] = y1;
out[6] = z1;
out[7] = 0;
out[8] = x2;
out[9] = y2;
out[10] = z2;
out[11] = 0;
out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);
out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);
out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);
out[15] = 1;
};
And here is the main.c , where I render things:
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
#include "include/matrix.h"
#include "include/io.h"
const int WIDTH = 640;
const int HEIGHT = 480;
// called when user resizes window
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
glViewport(0, 0, width, height);
}
// called when we receive input
void processInput(GLFWwindow *window) {
if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, 1);
}
GLuint get_checker_texture() {
unsigned char texDat[64];
for (int i = 0; i < 64; ++i)
texDat[i] = ((i + (i / 8)) % 2) * 128 + 127;
//upload to GPU texture
GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, 8, 8, 0, GL_RED, GL_UNSIGNED_BYTE, texDat);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
return tex;
}
//void render_box(renderable* this, unsigned int vbo, unsigned int vao, unsigned int ebo) {
// draw_texture(this->texture, this->x, this->y, this->z, vbo, vao, ebo);
//}
int main(int argc, char* argv[]) {
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // only on MACOS
#endif
// creating the window
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "OpenGL App", NULL, NULL);
if (window == NULL) {
printf("Failed to create GLFW window");
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// hook on window resize
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
printf("Failed to initialize GLAD");
return -1;
}
printf("OpenGL %d.%d\n", GLVersion.major, GLVersion.minor);
glEnable(GL_DEPTH_TEST);
glViewport(0, 0, WIDTH, HEIGHT);
unsigned int tex = get_checker_texture();
const char* vertex_shader_src = read_file("res/shaders/textured_and_positioned.vs.glsl");
unsigned int vertex_shader;
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_src, NULL);
glCompileShader(vertex_shader);
int success;
char infoLog[512];
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(vertex_shader, 512, NULL, infoLog);
printf("%s\n", infoLog);
}
const char* fragment_shader_src = read_file("res/shaders/textured_and_positioned.fs.glsl");
unsigned int fragment_shader;
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_src, NULL);
glCompileShader(fragment_shader);
int success0;
char infoLog0[512];
glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success0);
if (!success0) {
glGetShaderInfoLog(fragment_shader, 512, NULL, infoLog0);
printf("%s\n", infoLog0);
}
unsigned int shaderProgram;
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertex_shader);
glAttachShader(shaderProgram, fragment_shader);
glLinkProgram(shaderProgram);
unsigned uniform_sampler_ourTexture = glGetUniformLocation(shaderProgram, "ourTexture");
unsigned uniform_mat4_model = glGetUniformLocation(shaderProgram, "model");
unsigned uniform_mat4_view = glGetUniformLocation(shaderProgram, "view");
unsigned uniform_mat4_perspective = glGetUniformLocation(shaderProgram, "perspective");
int success1;
char infoLog1[512];
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success1);
if(!success1) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog1);
printf("%s\n", infoLog1);
}
float vertices[] = {
// positions // colors // texture coords
0.1f, 0.1f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right
0.1f, -0.1f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right
-0.1f, -0.1f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left
-0.1f, 0.1f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0 // top left
};
unsigned elements[] = {
0, 1, 2, // triangle
2, 3, 0 // triangle
};
unsigned int vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
matrix4x4 model = init_matrix4x4();
matrix4x4 view = init_matrix4x4();
translate_matrix4x4(&view, 0.0f, 0.0f, 0.0f);
float x = 0.0f;
float y = 0.0f;
float z = 0.0f;
matrix4x4 perspective = calloc(16, sizeof(float));
ortho_matrix4x4(&perspective, 0.0f, 640.0f, 0.0f, 480.0f, 0.1f, 100.0f);
unsigned int vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// positions
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(0 * sizeof(float)));
glEnableVertexAttribArray(0);
// colors
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// texture coords
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
unsigned int ebo;
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
glUseProgram(shaderProgram);
glUniformMatrix4fv(uniform_mat4_view, 1, GL_FALSE, view);
glUniformMatrix4fv(uniform_mat4_perspective, 1, GL_FALSE, perspective);
// render loop
while(!glfwWindowShouldClose(window)) {
processInput(window);
// render here
glClearColor(
0, 0, 0, 0
);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex);
glUniform1i(uniform_sampler_ourTexture, 0);
translate_matrix4x4(&model, x, y, z);
glUniformMatrix4fv(uniform_mat4_model, 1, GL_FALSE, model);
//x += 0.0001f;
//y += 0.0001f;
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
Here is the vertex shader:
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;
uniform mat4 model;
uniform mat4 view;
uniform mat4 perspective;
out vec3 ourColor;
out vec2 TexCoord;
void main()
{
gl_Position = perspective * view * model * vec4(aPos, 1.0);
ourColor = aColor;
TexCoord = aTexCoord;
}
Here is the fragment shader:
#version 330 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;
uniform sampler2D ourTexture;
void main()
{
FragColor = vec4(vec3(texture(ourTexture, TexCoord).r), 1.);
}
Now, if I remove the perspective value from the shader, which is the ortho matrix, the checkered texture is rendered as it should.
What is wrong here?
Is it my shader or is it the matrix ortho function?
Your matrices are stored in row-major, submit them to the uniforms without transposing and do calculations left-associative in the shader.
You can either
store in column major order
or
transpose upon loading into the uniform
or
switch to left-associative multiplication in the shader
Each to the same effect.

Draw cubes with random colors using OpenGL

I want every cube to have a random color but with this code the colors keep changing all the time
int espacioX = -500;
int espacioY = -500;
for(int i=1; i<=100; i++){
for(int j=1; j<=100; j++){
randomR = (double)rand() / (RAND_MAX);
randomG = (double)rand() / (RAND_MAX);
randomB = (double)rand() / (RAND_MAX);
glColor3f(randomR,randomG,randomB);
glTranslatef(espacioX,espacioY,0);
glutSolidCube(9);
glTranslatef(-espacioX,-espacioY,0);
espacioX+=10;
}
glTranslatef(-1000,0,0);
espacioY+=10;
}
How do I make them stay in the same color while the program is running?
Edit:
This is the comple code:
#include <windows.h>
/***** OpenGL library imports. *****/
#include<gl\glut.h> //basic header file for OpenGL
//#include <gl\glaux.h> // Header File For The Glaux Library
/***** C library imports. *****/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
int ScreenWidth = 0;
int ScreenHeight = 0;
int last_x = 0, last_y = 0,left = 1,middle = 0,right = 0;
int zoom_y = 0;
int anglex=0, angley=0, anglez=0;
int lookfrom=450;
int ang=0;
void myGlutKeyboard(unsigned char Key, int x, int y)
{
printf("%5d\n",Key);
glutPostRedisplay();
}
void init_GL_params()
{
static GLfloat light_ambient[] = { .250, .250, .250, .250 };
static GLfloat light_diffuse[] = { .250, .250, .25, .250 };
static GLfloat light_specular[] = { .250, .250, .250, .250 };
static GLfloat light1_diffuse[] = { .250, .250, .250, .0 };
static GLfloat light1_specular[] = { .250, .250, .250, .0 };
glEnable (GL_LIGHTING);
glEnable (GL_LIGHT0);
glEnable (GL_LIGHT1);
glDisable (GL_TEXTURE_2D);
glDisable (GL_TEXTURE_GEN_S);
glDisable (GL_TEXTURE_GEN_T);
glShadeModel (GL_FLAT);
glEnable (GL_DEPTH_TEST);
glDepthFunc (GL_LESS);
glEnable (GL_CULL_FACE);
glCullFace (GL_BACK);
glFrontFace (GL_CCW);
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
glLightfv (GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv (GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv (GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT1, GL_DIFFUSE, light1_diffuse);
glLightfv(GL_LIGHT1, GL_SPECULAR, light1_specular);
glLightfv (GL_LIGHT1, GL_AMBIENT, light_ambient);
glColor3f (1.0, 1.0, 1.0);
}
void setLightPosition()
{
static GLfloat light_position[] = { 100, 200.0, 10, 1.0 };
static GLfloat light1_position[] = { -0.0, 300.0, 0.0, 1.0 };
// set the light position (for some reason we have to do this in model view.
glLightfv (GL_LIGHT0, GL_POSITION, light_position);
glLightfv(GL_LIGHT1, GL_POSITION, light1_position);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_COLOR_MATERIAL);
}
void myGlutDisplay(void)
{
init_GL_params();
// clear the window
glClearColor (0,0,0,0); //Color de fondo R G B
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();
setLightPosition(); //Posici{on de la fuente de luz
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective(60.0f, 1.0, 1.0f, 10000.0f);
gluLookAt( //punto de vista
0 ,100 ,lookfrom , // desde donde veo xyz
0, 0, 0, // hacia donde veo xyz
0,1,0 );
glRotatef(anglex, 1.0, 0.0, 0.0);
glRotatef(angley, 0.0, 1.0, 0.0);
glRotatef(anglez, 0.0, 0.0, 1.0);
//Empieza a dibujar
int espacioX = 500;
int espacioY = 500;
double randomR, randomG, randomB;
for(int i=1; i<=100; i++){
for(int j=1; j<=100; j++){
randomR = (double)rand() / (RAND_MAX);
randomG = (double)rand() / (RAND_MAX);
randomB = (double)rand() / (RAND_MAX);
glColor3f(randomR,randomG,randomB);
glTranslatef(espacioX,espacioY,0);
glutSolidCube(9);
glTranslatef(-espacioX,-espacioY,0);
espacioX-=10;
}
glTranslatef(1000,0,0);
espacioY-=10;
}
glFlush(); // Flush The GL Pipeline
glutSwapBuffers();
}
void myGlutReshape2(int mWidth, int mHeight)
{
ScreenWidth = mWidth;
ScreenHeight = mHeight;
glViewport(0, 0, (GLsizei) ScreenWidth, (GLsizei) ScreenHeight);
glutPostRedisplay();
}
/****************************************************************/
void myGlutIdle(void)
{
glutPostRedisplay();
}
/***************************************************************/
void myGlutMouse(int button, int button_state, int x, int y){
if ( (button == GLUT_LEFT_BUTTON) && (button_state == GLUT_DOWN) )
{
last_x = x;
last_y = y;
left = 1;
middle = 0;
right = 0;
}
else if ((button == GLUT_RIGHT_BUTTON) && (button_state == GLUT_DOWN) )
{
zoom_y = y;
right = 1;
left = 0;
middle = 0;
}
}
void myGlutMotion(int x, int y){
if (left){
anglex+= (float) (y - last_y);
angley+= (float) (x - last_x);
last_x = x;
last_y = y;
}
if (right)
{
lookfrom += (y - zoom_y);
zoom_y = y;
}
}
void GlutInit(int argc, char** argv)
{
ScreenWidth = 700;
ScreenHeight = 700;
/****************************************/
/* Initialize GLUT and create window */
/****************************************/
glutInit(&argc, argv);
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_STENCIL ); //set up the display as a double buffer using RGB values
glutInitWindowPosition(90, 50); //set the position of where you want the window to open
glutInitWindowSize(ScreenWidth, ScreenHeight); //set how big you want the initial window to be
glutCreateWindow("Testing Virtual Environment" ); //what do you want the window to be called (titlebar text)
//register callbacks
glutDisplayFunc(myGlutDisplay); //Register the display callback
glutReshapeFunc(myGlutReshape2); // -- Resize handler
glutKeyboardFunc(myGlutKeyboard); // -- Keyboard handler
glutMouseFunc(myGlutMouse); // -- Mouse Click handler
glutMotionFunc(myGlutMotion); // -- Mous motion handler
glutIdleFunc(myGlutIdle); // -- Idle handler
glFlush();
}
int main( int argc, char **argv )
{
GlutInit(argc, argv);
glutMainLoop();
return 0;
}
It was a sample code so I just posted the part that I edited, sorry. When I did a cube or a sphere with an specific color it always stayed the same so i didn't realiza that this refresh the image all the time. I don't really understand the whole thing so I don't know where it's refreshing the image.
Why not set SEED to some constant value at start of myGlutDisplay(void). That will give you the same random values each frame without any big change in your code for example like this:
void myGlutDisplay(void)
{
init_GL_params();
// clear the window
glClearColor (0,0,0,0); //Color de fondo R G B
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();
setLightPosition(); //Posici{on de la fuente de luz
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective(60.0f, 1.0, 1.0f, 10000.0f);
gluLookAt( //punto de vista
0 ,100 ,lookfrom , // desde donde veo xyz
0, 0, 0, // hacia donde veo xyz
0,1,0 );
glRotatef(anglex, 1.0, 0.0, 0.0);
glRotatef(angley, 0.0, 1.0, 0.0);
glRotatef(anglez, 0.0, 0.0, 1.0);
//Empieza a dibujar
int espacioX = 500;
int espacioY = 500;
double randomR, randomG, randomB;
srand(0x98765432); // this is the SEED
for(int i=1; i<=100; i++){
for(int j=1; j<=100; j++){
randomR = (double)rand() / (RAND_MAX);
randomG = (double)rand() / (RAND_MAX);
randomB = (double)rand() / (RAND_MAX);
glColor3f(randomR,randomG,randomB);
glTranslatef(espacioX,espacioY,0);
glutSolidCube(9);
glTranslatef(-espacioX,-espacioY,0);
espacioX-=10;
}
glTranslatef(1000,0,0);
espacioY-=10;
}
glFlush(); // Flush The GL Pipeline
glutSwapBuffers();
}
The value of the SEED will give you the pattern. So changing the constant will change the colors. Beware wrong constant (like 0) can corrupt the randomness of the rand() function.
It seems like you are running this code inside another loop which means you are calculating your random variables every time the scene is redrawn, this would cause the colors to change and the obvious solution would be to poulate your list of cubes once and then iterate through the list drawing the cubes on each scene refresh.
However, without seeing the rest of your code it is unclear. Please include more information so we can give you a better answer.

SDL2 / OpenGL program works on one PC but not on the other

On my Desktop PC (Linux, OpenSuse 42.2, GraKa: Nvidia GTX 960) the program down below works fine. It opens a window with three axes X, Y, Z in red, green, blue and you can use the arrow buttons to move the camera around the axis.
On my Linux Laptop (OpenSuse 42.3, Mesa DRI on Intel 5500) the program just displays a black screen but no axes.
"glxgears" runs fine on the laptop, so OpenGL in principle must work.
To my understanding I must have programmed something not in a portable way, somewhere relied on something that I shouldn't have.
I have re-read several tutorials for SDL2, but I don't see what I was missing or doing incorrectly.
How can I find out if my program is written portably, or better how can I find the non-portable parts?
Compilerflags:
`sdl2-config --cflags` -I. -Isrc -g
Linkerflags:
`sdl2-config --libs` -lGLEW -lGL -lpthread -lm
main.c:
#include <GL/glew.h>
#include <GL/glu.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>
#include "gl_common.h"
int width, height;
SDL_Surface* screen;
SDL_Surface* image;
int stop;
SDL_Window* window = NULL;
SDL_GLContext context;
int joy;
float wx, wy;
float ra;
float dx = 0.05;
float dy = 0.05;
float dr = 0.005;
Uint32 last_time;
static float c = M_PI / 180.0;
GLfloat cam_x, cam_y, cam_z;
GLuint program_object;
int is_initialised = 0;
GLfloat u_mvp[16];
GLint u_mvp_loc;
#define AL 1.4
#define AX 0.15
#define AY 0.05
GLfloat axis[] = {
// x, red
0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
AL, 0.0, 0.0, 1.0, 0.0, 0.0,
AL - AX, AY, 0.0, 1.0, 0.0, 0.0,
AL - AX, -AY, 0.0, 1.0, 0.0, 0.0,
AL, 0.0, 0.0, 1.0, 0.0, 0.0,
AL - AX, 0.0, AY, 1.0, 0.0, 0.0,
AL - AX, 0.0, -AY, 1.0, 0.0, 0.0,
AL, 0.0, 0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
// y, green
0.0, 0.0, 0.0, 0.0, 1.0, 0.0,
0.0, AL, 0.0, 0.0, 1.0, 0.0,
0.0, AL-AX, AY, 0.0, 1.0, 0.0,
0.0, AL-AX, -AY, 0.0, 1.0, 0.0,
0.0, AL, 0.0, 0.0, 1.0, 0.0,
AY, AL-AX, 0.0, 0.0, 1.0, 0.0,
-AY, AL-AX, 0.0, 0.0, 1.0, 0.0,
0.0, AL, 0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 0.0, 1.0, 0.0,
// z, blue
0.0, 0.0, 0.0, 0.0, 0.0, 1.0,
0.0, 0.0, AL, 0.0, 0.0, 1.0,
AY, 0.0, AL-AX, 0.0, 0.0, 1.0,
-AY, 0.0, AL-AX, 0.0, 0.0, 1.0,
0.0, 0.0, AL, 0.0, 0.0, 1.0,
0.0, AY, AL-AX, 0.0, 0.0, 1.0,
0.0, -AY, AL-AX, 0.0, 0.0, 1.0,
0.0, 0.0, AL, 0.0, 0.0, 1.0,
0.0, 0.0, 0.0, 0.0, 0.0, 1.0,
};
#define AXIS_SIZE (sizeof(axis) / 6 / sizeof(GLfloat))
void quit(void) {
SDL_GL_DeleteContext(context);
SDL_DestroyWindow(window);
SDL_Quit();
}
void draw() {
GLfloat proj_mat[16];
GLfloat model_mat[16];
GLfloat model_mat2[16];
GLfloat ctr[3];
GLfloat eye[3];
GLfloat up[3];
glViewport(0, 0, width, height);
mat_glu_perspective(proj_mat, 45.0f, (GLfloat)(width) / height, 0.1f, 100.0f);
#if 0
printf("\n\nproj_mat\n");
mat_show(u_mvp);
#endif
eye[0] = cam_x;
eye[1] = cam_y;
eye[2] = cam_z;
ctr[0] = 0.0;
ctr[1] = 0.0;
ctr[2] = 0.0;
up[0] = 0.0;
up[1] = 0.0;
up[2] = 1.0;
mat_glu_look_at(model_mat, eye, ctr, up);
mat_mul(u_mvp, proj_mat, model_mat);
#if 0
printf("\n\nu_mvp\n");
mat_show(u_mvp);
#endif
glUniformMatrix4fv(u_mvp_loc, 1, GL_FALSE, u_mvp);
glClearColor ( 0.0, 0.0, 0.0, 1.0 );
glClear(GL_COLOR_BUFFER_BIT);
glClear(GL_DEPTH_BUFFER_BIT);
// glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
// glCullFace(GL_FRONT_AND_BACK);
glUseProgram(program_object);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_TRUE, 6 * sizeof(GLfloat), axis);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_TRUE, 6 * sizeof(GLfloat), axis+3);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
// glDisableVertexAttribArray(2);
// glDisableVertexAttribArray(3);
glDrawArrays(GL_LINE_STRIP, 0, AXIS_SIZE);
SDL_GL_SwapWindow(window);
}
void init_gl(void) {
const char* vsh;
const char* fsh;
GLuint vertex_shader;
GLuint fragment_shader;
GLint linked;
vsh = load_file("shader.vsh");
fsh = load_file("shader.fsh");
fprintf(stderr, "vertex shader\n");
vertex_shader = load_shader(GL_VERTEX_SHADER, vsh);
fprintf(stderr, "fragment shader\n");
fragment_shader = load_shader(GL_FRAGMENT_SHADER, fsh);
program_object = glCreateProgram();
if(program_object == 0) {
printf("program object is 0\n");
exit(-10);
}
glAttachShader(program_object, vertex_shader);
glAttachShader(program_object, fragment_shader);
glBindAttribLocation(program_object, 0, "a_pos");
glBindAttribLocation(program_object, 1, "a_col");
glLinkProgram(program_object);
glGetProgramiv(program_object, GL_LINK_STATUS, &linked);
if(!linked) {
GLint info_len;
glGetProgramiv(program_object, GL_INFO_LOG_LENGTH, &info_len);
if(info_len > 1) {
char* info_log = (char*)malloc(info_len);
glGetProgramInfoLog(program_object, info_len, NULL, info_log);
fprintf(stderr, "<%s>\n\n", info_log);
free(info_log);
exit(-1);
}
glDeleteProgram(program_object);
exit(-11);
}
mat_identity(u_mvp);
u_mvp_loc = glGetUniformLocation(program_object, "u_mvp");
}
void update_cam(void) {
cam_x = ra*cos(c*wx)*cos(c*wy);
cam_y = ra*sin(c*wx)*cos(c*wy);
cam_z = ra*sin(c*wy);
}
void left(Uint32 d) {
wx -= dx*d;
if(wx < 0.0) wx += 360.0;
update_cam();
}
void right(Uint32 d) {
wx += dx*d;
if(wx > 360.0) wx -= 360.0;
update_cam();
}
void up(Uint32 d) {
if(wy + dy*d < 90.0) {
wy += dy*d;
update_cam();
}
}
void down(Uint32 d) {
if(wy - dy*d > -90.0) {
wy -= dy*d;
update_cam();
}
}
void zoom_in(Uint32 d) {
if(ra > 1.0) ra -= dr*d;
update_cam();
}
void zoom_out(Uint32 d) {
if(ra < 30.0) ra += dr*d;
update_cam();
}
static Uint32 time_diff(void) {
Uint32 ret;
Uint32 now = SDL_GetTicks();
ret = now - last_time;
last_time = now;
return ret;
}
int main(int argc, char** argv) {
SDL_Event event;
int k;
Uint32 d;
atexit(quit);
if(SDL_Init(SDL_INIT_VIDEO) < 0) {
printf("couldn't init: %s\n", SDL_GetError());
exit(-1);
}
width = 1024;
height = 768;
//Use OpenGL 3.2 core
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 3 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 2 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1);
window = SDL_CreateWindow( "SDL OpenGL exaple", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL );
if( window == NULL ) {
printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
exit(-2);
}
context = SDL_GL_CreateContext( window );
if( context == NULL ) {
printf( "OpenGL context could not be created! SDL Error: %s\n", SDL_GetError() );
exit(-3);
}
glewExperimental = GL_TRUE;
GLenum glewError = glewInit();
if( glewError != GLEW_OK ) {
printf( "Error initializing GLEW! %s\n", glewGetErrorString( glewError ) );
exit(-4);
}
screen = SDL_GetWindowSurface( window );
init_gl();
is_initialised = 1;
wx = 150.0;
wy = 0.0;
ra = 4.0;
update_cam();
d = time_diff();
joy = 0;
stop = 0;
while(!stop) {
while(SDL_PollEvent(&event)) {
switch(event.type) {
case SDL_QUIT:
do_exit:
exit(-1);
stop = 1;
break;
case SDL_KEYDOWN:
switch(event.key.keysym.sym) {
case SDLK_ESCAPE:
case 'q':
goto do_exit;
break;
case SDLK_LEFT:
joy |= 4;
break;
case SDLK_RIGHT:
joy |= 8;
break;
case SDLK_UP:
joy |= 1;
break;
case SDLK_DOWN:
joy |= 2;
break;
case SDLK_PAGEUP:
joy |= 16;
break;
case SDLK_PAGEDOWN:
joy |= 32;
break;
}
break;
case SDL_KEYUP:
switch(event.key.keysym.sym) {
case SDLK_LEFT:
joy &= ~4;
break;
case SDLK_RIGHT:
joy &= ~8;
break;
case SDLK_UP:
joy &= ~1;
break;
case SDLK_DOWN:
joy &= ~2;
break;
case SDLK_PAGEUP:
joy &= ~16;
break;
case SDLK_PAGEDOWN:
joy &= ~32;
break;
}
break;
}
}
d = time_diff();
if(joy & 1) up(d);
if(joy & 2) down(d);
if(joy & 4) left(d);
if(joy & 8) right(d);
if(joy & 16) zoom_in(d);
if(joy & 32) zoom_out(d);
draw();
}
return 0;
}
gl_common.c:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "gl_common.h"
// Matrizen werden spaltenweise angegeben
#define IX(x, y) ((y) + ((x) * 4))
void mat_show(GLfloat m[]) {
int x, y, i;
for(y = 0; y < 4; y++) {
for(x = 0; x < 4; x++) {
i = IX(x, y);
printf("%8.5f ", m[i]);
}
printf("\n");
}
}
GLfloat vec_len(GLfloat x[]) {
return sqrt((x[0]) * (x[0]) + (x[1]) * (x[1]) + (x[2]) * (x[2]));
}
void vec_norm(GLfloat x[]) {
GLfloat l = vec_len(x);
x[0] /= l;
x[1] /= l;
x[2] /= l;
}
void vec_copy(GLfloat dest[], const GLfloat src[]) {
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
}
void vec_diff(GLfloat res[], const GLfloat a[], const GLfloat b[]) {
res[0] = a[0] - b[0];
res[1] = a[1] - b[1];
res[2] = a[2] - b[2];
}
void vec_cross_product(GLfloat res[], const GLfloat a[], const GLfloat b[]) {
res[0] = a[1]*b[2] - b[1]*a[2];
res[1] = a[2]*b[0] - b[2]*a[0];
res[2] = a[0]*b[1] - b[0]*a[1];
}
GLfloat vec_scalar_product(const GLfloat a[], const GLfloat b[]) {
return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
}
void mat_identity(GLfloat res[]) {
res[0] = 1.0f;
res[1] = 0.0f;
res[2] = 0.0f;
res[3] = 0.0f;
res[4] = 0.0f;
res[5] = 1.0f;
res[6] = 0.0f;
res[7] = 0.0f;
res[8] = 0.0f;
res[9] = 0.0f;
res[10] = 1.0f;
res[11] = 0.0f;
res[12] = 0.0f;
res[13] = 0.0f;
res[14] = 0.0f;
res[15] = 1.0f;
}
void mat_mul(GLfloat res[], const GLfloat a[], const GLfloat b[]) {
GLfloat tmp;
int x, y, i;
for(y = 0; y < 4; y++) {
for(x = 0; x < 4; x++) {
tmp = 0.0f;
for(i = 0; i < 4; i++) {
tmp += a[IX(i, y)] * b[IX(x, i)];
}
res[IX(x, y)] = tmp;
}
}
}
void mat_glu_look_at(GLfloat res[],
const GLfloat eye[],
const GLfloat center[],
const GLfloat up[])
{
GLfloat f[3]; // forward
GLfloat upc[3]; // up copy
GLfloat s[3]; // side
GLfloat u[3]; // up
GLfloat tmp[16];
GLfloat trl[16];
vec_diff(f, center, eye);
vec_norm(f);
vec_copy(upc, up);
vec_cross_product(s, f, upc);
vec_cross_product(u, s, f);
vec_norm(s);
vec_norm(u);
tmp[0] = s[0];
tmp[1] = u[0];
tmp[2] = -f[0];
tmp[3] = 0.0f;
tmp[4] = s[1];
tmp[5] = u[1];
tmp[6] = -f[1];
tmp[7] = 0.0f;
tmp[8] = s[2];
tmp[9] = u[2];
tmp[10] = -f[2];
tmp[11] = 0.0f;
tmp[12] = 0.0f;
tmp[13] = 0.0f;
tmp[14] = 0.0f;
tmp[15] = 1.0f;
mat_identity(trl);
trl[12] = -eye[0];
trl[13] = -eye[1];
trl[14] = -eye[2];
mat_mul(res, tmp, trl);
}
void mat_glu_perspective(GLfloat res[], GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar) {
GLfloat sine, cotangent, deltaZ;
GLfloat radians = fovy / 2 * 3.1415926536 / 180;
deltaZ = zFar - zNear;
sine = sin(radians);
if ((deltaZ == 0) || (sine == 0) || (aspect == 0)) {
return;
}
cotangent = cos(radians) / sine;
res[0] = cotangent / aspect;
res[1] = 0.0;
res[2] = 0.0;
res[3] = 0.0;
res[4] = 0.0;
res[5] = cotangent;
res[6] = 0.0;
res[7] = 0.0;
res[8] = 0.0;
res[9] = 0.0;
res[10] = -(zFar + zNear) / deltaZ;
res[11] = -1.0;
res[12] = 0.0;
res[13] = 0.0;
res[14] = -2 * zNear * zFar / deltaZ;
res[15] = 0.0;
}
///////////
GLuint load_shader(GLenum type, const char* src) {
GLuint shader;
GLint compiled;
shader = glCreateShader(type);
if(shader == 0) return 0;
glShaderSource(shader, 1, &src, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
if(!compiled) {
GLint info_len;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_len);
if(info_len > 1) {
char* info_log = (char*)malloc(info_len);
glGetShaderInfoLog(shader, info_len, NULL, info_log);
fprintf(stderr, "<<<\n%s\n>\n\n", info_log);
free(info_log);
}
glDeleteShader(shader);
exit(-1);
return 0;
}
return shader;
}
const char* load_file(const char* fname) {
FILE* fd;
const char* ret;
size_t len;
fd = fopen(fname, "rb");
if(fd == NULL) {
fprintf(stderr, "could not load <%s>\n", fname);
return NULL;
}
fseek(fd, -1, SEEK_END);
len = ftell(fd);
rewind(fd);
ret = (const char*)malloc(len + 1);
if(ret == NULL) {
fclose(fd);
fprintf(stderr, "could not get memory <%i>\n", len);
fclose(fd);
return NULL;
}
fread((void*)ret, 1, len, fd);
((char*)ret)[len] = 0;
// fprintf(stdout, "<%s>\n\n", ret);
return ret;
}
gl_common.h:
#ifndef GL_COMMON_H
#define GL_COMMON_H 1
#include <GL/glew.h>
#include <GL/gl.h>
#include <stdio.h>
#define QWE fprintf(stderr, "%s, %i\n", __FILE__, __LINE__)
typedef struct {
GLuint program_object;
int width;
int height;
GLfloat cam_x;
GLfloat cam_y;
GLfloat cam_z;
} UserData;
extern GLuint texbase[];
extern GLuint load_shader(GLenum type, const char* src);
extern const char* load_file(const char* fname);
/* math stuff */
extern GLfloat vec_len(GLfloat x[]);
extern void vec_norm(GLfloat x[]);
extern void vec_copy(GLfloat dest[], const GLfloat src[]);
extern void vec_diff(GLfloat res[], const GLfloat a[], const GLfloat b[]);
extern void vec_cross_product(GLfloat res[], const GLfloat a[], const GLfloat b[]);
extern GLfloat vec_scalar_product(const GLfloat a[], const GLfloat b[]);
extern void mat_mul(GLfloat res[], const GLfloat a[], const GLfloat b[]);
extern void mat_identity(GLfloat res[]);
extern void mat_glu_look_at(GLfloat res[],
const GLfloat eye[],
const GLfloat center[],
const GLfloat up[]);
extern void mat_glu_perspective(GLfloat res[], GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar);
extern void mat_show(GLfloat m[]);
#endif
shader.fsh:
#version 130
precision mediump float;
varying vec4 v_col;
void main()
{
gl_FragColor = v_col;
}
shader.vsh:
#version 130
uniform mat4 u_mvp;
attribute vec4 a_pos;
attribute vec4 a_col;
varying vec4 v_col;
const float c_zero = 0.0;
const float c_one = 1.0;
void main()
{
gl_Position = u_mvp * a_pos;
v_col = a_col;
}

Objects don't cast shadows on other objects

I made a OpenGL program with GLEW and GLFW on Orwell Dev-C++ 5.4.0 which shows blocks. I added ambient, diffuse and specular light and now shadows, too. I used a depth texture. But now, the blocks don't cast shadows on other blocks, rather only on themselves!
This is the important part of my source code:
void createShadows()
{
int error;
glGenFramebuffers(1, &buffers.depthFbo);
glBindFramebuffer(GL_FRAMEBUFFER, buffers.depthFbo);
glGenTextures(1, &buffers.depthTbo);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, buffers.depthTbo);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, winInfo.winWidth, winInfo.winHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, buffers.depthTbo, 0);
glDrawBuffer(GL_NONE);
error = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(error != GL_FRAMEBUFFER_COMPLETE)
printError("FramebufferError.txt", "Framebuffer", error);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void init()
{
renderProg = compileShaders("openglSuperTutorials12.vss", "openglSuperTutorials12.fss", 0);
renderProgDepth = compileShaders("openglSuperTutorials12_depth.vss", "openglSuperTutorials12_depth.fss", 0);
glGenVertexArrays(1, &buffers.vao);
glBindVertexArray(buffers.vao);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
matrices.mMatrixDepth = glm::mat4(1.0f);
matrices.pMatrixDepth = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, -10.0f, 20.0f);
matrices.biasMatrixDepth = glm::mat4(0.5f, 0.0f, 0.0f, 0.0f,
0.0f, 0.5f, 0.0f, 0.0f,
0.0f, 0.0f, 0.5f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f);
//Initialize light and material properties and give them to the "renderProg" (truncated)
glfwGetWindowSize(window, &winInfo.winWidth, &winInfo.winHeight);
glfwSetCursorPos(window, winInfo.winWidth/2.0, winInfo.winHeight/2.0);
createTexture();
createVertices();
createBlocks();
createShadows();
}
void setBlock(glm::vec3 position, int id, int depth)
{
if(depth != 1)
{
matrices.mMatrix = glm::translate(glm::mat4(1.0f), position);
matrices.mvpMatrixBiasDepth = matrices.biasMatrixDepth * matrices.mvpMatrixDepth;
glUniformMatrix4fv(glGetUniformLocation(renderProg, "mMatrix"), 1, GL_FALSE, &matrices.mMatrix[0][0]);
glUniformMatrix4fv(glGetUniformLocation(renderProg, "mvpMatrixBiasDepth"), 1, GL_FALSE, &matrices.mvpMatrixBiasDepth[0][0]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, buffers.tbo);
glUniform1i(glGetUniformLocation(renderProg, "texBlock"), 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, buffers.depthTbo);
glUniform1i(glGetUniformLocation(renderProg, "shadowMap"), 1);
glGenBuffers(1, &buffers.tcbo);
glBindBuffer(GL_ARRAY_BUFFER, buffers.tcbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(blocks[id]), blocks[id], GL_DYNAMIC_DRAW);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(1);
}
else
{
matrices.mvpMatrixDepth = matrices.pMatrixDepth * matrices.vMatrixDepth * matrices.mMatrixDepth;
glUniformMatrix4fv(glGetUniformLocation(renderProgDepth, "mvpMatrixDepth"), 1, GL_FALSE, &matrices.mvpMatrixDepth[0][0]);
}
glDrawArrays(GL_TRIANGLES, 0, 36);
if(depth != 1)
{
glDisableVertexAttribArray(1);
glDeleteBuffers(1, &buffers.tcbo);
}
}
void display()
{
int x, y, z;
GLfloat bgColor[] = { 0.0f, 0.73f, 1.0f, 1.0f };
GLfloat depthOne = 1.0f;
glBindFramebuffer(GL_FRAMEBUFFER, buffers.depthFbo);
glClearBufferfv(GL_DEPTH, 0, &depthOne);
glUseProgram(renderProgDepth);
glEnableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
if(viewPos.lightSticky == 1)
{
lightProperties.lightPosition = glm::vec3(viewPos.eyeX, viewPos.eyeY, viewPos.eyeZ);
lightProperties.lightDirection = glm::vec3(viewPos.centerX, viewPos.centerY, viewPos.centerZ);
}
matrices.vMatrixDepth = glm::lookAt(
lightProperties.lightPosition,
lightProperties.lightDirection,
glm::vec3(viewPos.upX, viewPos.upY, viewPos.upZ));
for(z=-5; z<=5; z++)
{
for(y=0; y<=6; y++)
{
for(x=-5; x<=5; x++)
{
if(blockMap[z+5][y][x+5].id != -1)
setBlock(blockMap[z+5][y][x+5].position, blockMap[z+5][y][x+5].id, 1);
}
}
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearBufferfv(GL_COLOR, 0, bgColor);
glClearBufferfv(GL_DEPTH, 0, &depthOne);
glUseProgram(renderProg);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
lightProperties.cameraPosition = glm::vec3(viewPos.eyeX, viewPos.eyeY, viewPos.eyeZ);
matrices.vMatrix = glm::lookAt(glm::vec3(viewPos.eyeX, viewPos.eyeY, viewPos.eyeZ),
glm::vec3(viewPos.centerX, viewPos.centerY, viewPos.centerZ),
glm::vec3(viewPos.upX, viewPos.upY, viewPos.upZ));
matrices.pMatrix = glm::perspective(45.0f, (GLfloat)winInfo.winWidth/(GLfloat)winInfo.winHeight, 0.1f, 1000.0f);
glUniformMatrix4fv(glGetUniformLocation(renderProg, "vMatrix"), 1, GL_FALSE, &matrices.vMatrix[0][0]);
glUniformMatrix4fv(glGetUniformLocation(renderProg, "pMatrix"), 1, GL_FALSE, &matrices.pMatrix[0][0]);
//Update light uniforms (truncated)
for(z=-5; z<=5; z++)
{
for(y=0; y<=6; y++)
{
for(x=-5; x<=5; x++)
{
if(blockMap[z+5][y][x+5].id != -1)
setBlock(blockMap[z+5][y][x+5].position, blockMap[z+5][y][x+5].id, 0);
}
}
}
glfwSwapBuffers(window);
winInfo.frames++;
}
The Vertex-Shader "openglSuperTutorials12.vss":
#version 430 core
layout (location = 0) in vec3 vPosition;
layout (location = 1) in vec2 vTexCoord;
layout (location = 2) in vec3 vNormal;
out vec3 fPosition;
out vec4 fShadowCoord;
out vec2 fTexCoord;
out vec3 fNormal;
uniform mat4 mMatrix;
uniform mat4 vMatrix;
uniform mat4 pMatrix;
uniform mat4 mvpMatrixBiasDepth;
void main()
{
gl_Position = pMatrix * vMatrix * mMatrix * vec4(vPosition, 1.0);
fPosition = vPosition;
fShadowCoord = mvpMatrixBiasDepth * vec4(vPosition, 1.0);
fTexCoord = vTexCoord;
fNormal = normalize(transpose(inverse(mat3(mMatrix))) * vNormal);
}
The Fragment-Shader "openglSuperTutorials12.fss":
#version 430 core
in vec3 fPosition;
in vec4 fShadowCoord;
in vec2 fTexCoord;
in vec3 fNormal;
out vec4 outColor;
uniform sampler2D texBlock;
uniform sampler2D shadowMap;
uniform mat4 mMatrix;
uniform int ambientLightEnabled;
uniform int diffuseLightEnabled;
uniform int specularLightEnabled;
uniform int shadowsEnabled;
uniform vec3 ambientLightColor;
uniform vec3 diffuseLightColor;
uniform vec3 specularLightColor;
uniform vec3 lightPosition;
uniform vec3 cameraPosition;
uniform float lightAttenuation;
uniform vec3 spotlightConeDirection;
uniform float spotlightCosCutoff;
uniform float spotlightExponent;
uniform vec3 ambientMaterialColor;
uniform vec3 diffuseMaterialColor;
uniform vec3 specularMaterialColor;
uniform float shininess;
uniform float strength;
void main()
{
vec3 shadowValue = vec3(textureProj(shadowMap, fShadowCoord));
vec3 surfacePos = vec3(mMatrix * vec4(fPosition, 1.0));
vec3 surfaceToLight = normalize(lightPosition - surfacePos);
vec3 surfaceToCamera = normalize(cameraPosition - surfacePos);
vec3 ambientColor = ambientMaterialColor * ambientLightColor;
float diffuseIntensity = max(0.0, dot(fNormal, surfaceToLight));
vec3 diffuseColor = diffuseIntensity * diffuseLightColor * diffuseMaterialColor;
float specularIntensity;
if(diffuseIntensity == 0.0)
specularIntensity = 0.0;
else
specularIntensity = pow(max(0.0, dot(fNormal, normalize(surfaceToLight + surfaceToCamera))), shininess) * strength;
vec3 specularColor = specularIntensity * specularLightColor * specularMaterialColor;
float distanceToLight = length(surfacePos - lightPosition);
float attenuation = 1.0 / (
lightAttenuation +
lightAttenuation * distanceToLight +
lightAttenuation * distanceToLight * distanceToLight);
vec3 lightColorCombined = vec3(0.0);
if(ambientLightEnabled == 1)
{
lightColorCombined += ambientColor;
}
if(diffuseLightEnabled == 1)
{
if(shadowsEnabled == 1)
diffuseColor *= shadowValue;
lightColorCombined += diffuseColor;
}
if(specularLightEnabled == 1)
{
if(shadowsEnabled == 1)
specularColor *= shadowValue;
lightColorCombined += attenuation * specularColor;
}
outColor = texture(texBlock, fTexCoord) * vec4(lightColorCombined, 1.0);
}
The other shaders ("openglSuperTutorials12_depth.vss" and "openglSuperTutorials12_depth.fss") are only simple pass-through shaders with the "mvpMatrixDepth".
A screenshot of the scene
What do I have to change to let the light cast shadows on other objects?

OpenGL sphere camera: cube rendering incorrectly

I implement a simple sphere camera by using OpenGL and I render a cube for observasion. But the cube is not displayed correctly. Like this:
Some surfaces of the cube are invisible, some are not. Can someone solve the problem? Here is the code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <gl/glut.h>
#define MAX_EPSILON_ERROR 10.0f
#define THRESHOLD 0.30f
#define REFRESH_DELAY 10 //ms
////////////////////////////////////////////////////////////////////////////////
// constants
const unsigned int window_width = 512;
const unsigned int window_height = 512;
// mouse controls
int mouse_old_x, mouse_old_y;
int mouse_buttons = 0;
float rotate_x = 0.0, rotate_y = 0.0;
float translate_z = -3.0;
// Auto-Verification Code
int fpsCount = 0; // FPS count for averaging
int fpsLimit = 1; // FPS limit for sampling
int g_Index = 0;
float avgFPS = 0.0f;
unsigned int frameCount = 0;
unsigned int g_TotalErrors = 0;
bool g_bQAReadback = false;
int *pArgc = NULL;
char **pArgv = NULL;
#define MAX(a,b) ((a > b) ? a : b)
////////////////////////////////////////////////////////////////////////////////
// declaration, forward
void cleanup();
// GL functionality
bool initGL(int *argc, char **argv);
// rendering callbacks
void display();
void keyboard(unsigned char key, int x, int y);
void mouse(int button, int state, int x, int y);
void motion(int x, int y);
void timerEvent(int value);
////////////////////////////////////////////////////////////////////////////////
// Program main
////////////////////////////////////////////////////////////////////////////////
int main(int argc, char **argv)
{
// First initialize OpenGL context
if (false == initGL(&argc, argv))
{
return false;
}
// register callbacks
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutMouseFunc(mouse);
glutMotionFunc(motion);
// start rendering mainloop
glutMainLoop();
atexit(cleanup);
return 0;
}
////////////////////////////////////////////////////////////////////////////////
//! Initialize GL
////////////////////////////////////////////////////////////////////////////////
bool initGL(int *argc, char **argv)
{
glutInit(argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
glutInitWindowSize(window_width, window_height);
glutCreateWindow("Cuda GL Interop (VBO)");
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutMotionFunc(motion);
glutTimerFunc(REFRESH_DELAY, timerEvent,0);
//// initialize necessary OpenGL extensions
//glewInit();
//if (! glewIsSupported("GL_VERSION_2_0 "))
//{
// fprintf(stderr, "ERROR: Support for necessary OpenGL extensions missing.");
// fflush(stderr);
// return false;
//}
// default initialization
glClearColor(0.0, 0.0, 0.0, 1.0);
glDisable(GL_DEPTH_TEST);
// viewport
glViewport(0, 0, window_width, window_height);
// projection
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat)window_width / (GLfloat) window_height, 2, 10.0);
// SDK_CHECK_ERROR_GL();
return true;
}
////////////////////////////////////////////////////////////////////////////////
//! Display callback
////////////////////////////////////////////////////////////////////////////////
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// set view matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0, 0.0, translate_z);
glRotatef(rotate_x, 1.0, 0.0, 0.0);
glRotatef(rotate_y, 0.0, 1.0, 0.0);
glBegin(GL_QUADS);
glColor3f(0.0f, 1.0f, 0.0f); // 颜色改成绿色
glVertex3f( 1.0f, 1.0f,-1.0f); // 四边形的右上顶点 (顶面)
glVertex3f(-1.0f, 1.0f,-1.0f); // 四边形的左上顶点 (顶面)
glVertex3f(-1.0f, 1.0f, 1.0f); // 四边形的左下顶点 (顶面)
glVertex3f( 1.0f, 1.0f, 1.0f); // 四边形的右下顶点 (顶面)
glColor3f(1.0f,0.5f,0.0f); // 颜色改成橙色
glVertex3f( 1.0f,-1.0f, 1.0f); // 四边形的右上顶点(底面)
glVertex3f(-1.0f,-1.0f, 1.0f); // 四边形的左上顶点(底面)
glVertex3f(-1.0f,-1.0f,-1.0f); // 四边形的左下顶点(底面)
glVertex3f( 1.0f,-1.0f,-1.0f); // 四边形的右下顶点(底面)
glColor3f(1.0f,0.0f,0.0f); // 颜色改成红色
glVertex3f( 1.0f, 1.0f, 1.0f); // 四边形的右上顶点(前面)
glVertex3f(-1.0f, 1.0f, 1.0f); // 四边形的左上顶点(前面)
glVertex3f(-1.0f,-1.0f, 1.0f); // 四边形的左下顶点(前面)
glVertex3f( 1.0f,-1.0f, 1.0f); // 四边形的右下顶点(前面)
glColor3f(1.0f,1.0f,0.0f); // 颜色改成黄色
glVertex3f( 1.0f,-1.0f,-1.0f); // 四边形的右上顶点(后面)
glVertex3f(-1.0f,-1.0f,-1.0f); // 四边形的左上顶点(后面)
glVertex3f(-1.0f, 1.0f,-1.0f); // 四边形的左下顶点(后面)
glVertex3f( 1.0f, 1.0f,-1.0f); // 四边形的右下顶点(后面)
glColor3f(0.0f,0.0f,1.0f); // 颜色改成蓝色
glVertex3f(-1.0f, 1.0f, 1.0f); // 四边形的右上顶点(左面)
glVertex3f(-1.0f, 1.0f,-1.0f); // 四边形的左上顶点(左面)
glVertex3f(-1.0f,-1.0f,-1.0f); // 四边形的左下顶点(左面)
glVertex3f(-1.0f,-1.0f, 1.0f); // 四边形的右下顶点(左面)
glColor3f(1.0f,0.0f,1.0f); // 颜色改成紫罗兰色
glVertex3f( 1.0f, 1.0f,-1.0f); // 四边形的右上顶点(右面)
glVertex3f( 1.0f, 1.0f, 1.0f); // 四边形的左上顶点(右面)
glVertex3f( 1.0f,-1.0f, 1.0f); // 四边形的左下顶点(右面)
glVertex3f( 1.0f,-1.0f,-1.0f); // 四边形的右下顶点(右面)
glEnd();
glutSwapBuffers();
}
void timerEvent(int value)
{
glutPostRedisplay();
glutTimerFunc(REFRESH_DELAY, timerEvent,0);
}
void cleanup()
{
//sdkDeleteTimer(&timer);
}
////////////////////////////////////////////////////////////////////////////////
//! Keyboard events handler
////////////////////////////////////////////////////////////////////////////////
void keyboard(unsigned char key, int /*x*/, int /*y*/)
{
switch (key)
{
case (27) :
exit(EXIT_SUCCESS);
break;
}
}
////////////////////////////////////////////////////////////////////////////////
//! Mouse event handlers
////////////////////////////////////////////////////////////////////////////////
void mouse(int button, int state, int x, int y)
{
if (state == GLUT_DOWN)
{
mouse_buttons |= 1<<button;
}
else if (state == GLUT_UP)
{
mouse_buttons = 0;
}
mouse_old_x = x;
mouse_old_y = y;
}
void motion(int x, int y)
{
float dx, dy;
dx = (float)(x - mouse_old_x);
dy = (float)(y - mouse_old_y);
if (mouse_buttons & 1)
{
rotate_x += dy * 0.2f;
rotate_y += dx * 0.2f;
}
else if (mouse_buttons & 4)
{
translate_z += dy * 0.01f;
}
mouse_old_x = x;
mouse_old_y = y;
}
Left click for rotation, and right click to change the radius.
Request a depth buffer:
glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE);
^^^^^^^^^^
And enable depth testing:
glEnable(GL_DEPTH_TEST);

Resources