Reputation: 1
I need to draw a cube with OpenGL in C:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
GLuint program;
GLuint vao;
int frame = 0;
#define M_PI 3.14159
void matrixmultiply(GLfloat *out, GLfloat *multiplicant) {
GLfloat temp[16];
for(int x = 0; x < 16; x++){
temp[x] = out[x];
}
for(int x = 0; x < 4; x++) {
for(int y = 0; y < 4; y++) {
GLfloat sum = 0.0f;
for(int i = 0; i < 4; i++) {
GLfloat first = (temp[(x*4)+i]);
GLfloat second = (multiplicant[(i*4)+y]);
if((first < -0.001 || first > 0.001) && (second < -0.001 || second > -0.001)) {
sum += first * second;
}
}
out[(x*4)+y] = sum;
}
}
}
void identity(GLfloat *out) {
for(int x = 0; x < 16; x++) {
out[x] = 0.0f;
}
out[0] = 1.0f;
out[5] = 1.0f;
out[10] = 1.0f;
out[15] = 1.0f;
}
void translate(GLfloat *out, GLfloat *v) {
identity(out);
out[12] = v[0];
out[13] = v[1];
out[14] = v[2];
}
void scale(GLfloat *out, GLfloat *v) {
identity(out);
out[0] = v[0];
out[5] = v[1];
out[10] = v[2];
}
void scaleMatrix(GLfloat *out, GLfloat Sx, GLfloat Sy, GLfloat Sz) {
identity(out);
out[0] = Sx;
out[5] = Sy;
out[10] = Sz;
out[15] = 1.0f;
}
void rotatez(GLfloat *out, GLfloat a) {
identity(out);
out[0] = cos(a);
out[1] = sin(a);
out[4] = -1*sin(a);
out[5] = cos(a);
}
void normalize(GLfloat *x){
GLfloat laenge = 1/(sqrtf(x[0]* x[0] + x[1]*x[1] + x[2]*x[2]));
for(int i = 0; i <= 2; i++){
x[i] = x[i] * laenge;
}
}
void crossProduct(GLfloat *a, GLfloat *b, GLfloat *c){
c[0] = a[1] * b[2] - a[2] * b[1];
c[1] = a[2] * b[0] - a[0] * b[2];
c[2] = a[0] * b[1] - a[1] * b[0];
}
GLfloat dotProduct(GLfloat *eye, GLfloat *a){
return (-1) * (a[0] * eye[0] + a[1] * eye[1] + a[2] * eye[2]);
}
void lookAt(GLfloat *out, GLfloat *eye, GLfloat *center, GLfloat *up){
GLfloat n[3], u[3], v[3];
n[0] = eye[0] - center[0];
n[1] = eye[1] - center[1];
n[2] = eye[2] - center[2];
crossProduct(up, n, u);
crossProduct(n, u, v);
normalize(n);
normalize(u);
normalize(v);
printf("%f, %f, %f \n", u[0],u[1],u[2]);
out[0] = u[0];
out[1] = v[0];
out[2] = n[0];
out[3] = 0.0f;
out[4] = u[1];
out[5] = v[1];
out[6] = n[1];
out[7] = 0.0f;
out[8] = u[2];
out[9] = v[2];
out[10] = n[2];
out[11] = 0.0f;
out[12] = dotProduct(u, eye);
out[13] = dotProduct(v, eye);
out[14] = dotProduct(n, eye);
out[15] = 1.0f;
for(int i = 0; i <= 15; i++){
printf("%f ", out[i]);
if((i+1) % 4 == 0){
printf("\n");
}
}
}
void perspective(GLfloat *out, GLfloat fovy, GLfloat aspect, GLfloat near, GLfloat far){
if (fovy <= 0 || aspect <= 0 || near <= 0 || far <= 0) {
printf("Error: Invalid input values in perspective function.\n");
return;
}
GLfloat degreeToRadian = acos(-1.0f) / 180;
GLfloat top = near * tan(fovy/2 * degreeToRadian);
GLfloat right = top * aspect;
out[0] = near / right;
out[1] = 0.0f;
out[2] = 0.0f;
out[3] = 0.0f;
out[4] = 0.0f;
out[5] = near / top;
out[6] = 0.0f;
out[7] = 0.0f;
out[8] = 0.0f;
out[9] = 0.0f;
out[10] = (-1) * (far + near) / (far - near);
out[11] = (-2) * far * near / (far - near);
out[12] = 0.0f;
out[13] = 0.0f;
out[14] = -1.0f;
out[15] = 0.0f;
for(int i = 0; i <= 15; i++){
printf("%f ", out[i]);
if((i+1) % 4 == 0){
printf("\n");
}
}
}
void init(void) {
// create and compile vertex shader
const char *vertexText =
"#version 330 core\n"
"layout(location = 0) in vec3 aPosition;\n"
"layout (location = 1) in vec3 aColor;\n"
"out vec3 vertexColor;\n"
//"out float fragValue;\n"
//"uniform vec3 color;\n"
"uniform mat4 transformMatrix;\n"
"uniform mat4 projectionMatrix;\n"
"void main() {\n"
" vertexColor = aColor;\n"
//" gl_Position = vec4(aPosition, 0.0, 1.0);\n"
//" gl_Position = transformMatrix * gl_Position;\n"
//" fragValue = vertValue;\n"
"gl_Position = projectionMatrix * modelViewMatrix * vec4(aPosition, 1.0);\n"
"}\n";
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexText, NULL);
glCompileShader(vertexShader);
GLint status;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
if(!status) {
printf("Error compiling vertex shader:");
GLchar infoLog[1024];
glGetShaderInfoLog(vertexShader, 1024, NULL, infoLog);
printf(infoLog);
}
// create and compile fragment shader
const char *fragmentText =
"#version 330 core\n"
"in vec3 vertexColor;\n"
//"in float fragValue;\n"
"uniform vec3 fragColor1;\n"
"uniform vec3 fragColor2;\n"
"void main() {\n"
"gl_FragColor = vec4(vertexColor, 1.0);\n"
//3.2 smooth transition
//" gl_FragColor = vec4(mix(fragColor1, fragColor2, fragValue), 1.0);\n"
//3.2 step transition
//" gl_FragColor = vec4(mix(fragColor1, fragColor2, step(0.5, fragValue)), 1.0);\n"
//3.2 smoothstep transition
//" gl_FragColor = vec4(mix(fragColor1, fragColor2, smoothstep(0.4, 0.6, fragValue)), 1.0);\n"
//3.2 sine repeating pattern
//" gl_FragColor = vec4(mix(fragColor1, fragColor2, (sin(fragValue*12.5)+1.0)/2.0), 1.0);\n"
//3.2 sine stepped repeating pattern
//" gl_FragColor = vec4(step(0.5, mix(fragColor1, fragColor2, (sin(fragValue*12.5)+1.0)/2.0)), 1.0);\n"
"}\n";
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentText, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status);
if(!status) {
printf("Error compiling fragment shader:");
GLchar infoLog[1024];
glGetShaderInfoLog(fragmentShader, 1024, NULL, infoLog);
printf(infoLog);
}
// create and link shader program
program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &status);
if(!status) {
printf("Error linking program:");
GLchar infoLog[1024];
glGetProgramInfoLog(program, 1024, NULL, infoLog);
printf(infoLog);
}
glValidateProgram(program);
glGetProgramiv(program, GL_VALIDATE_STATUS, &status);
if(!status) {
printf("Error validating program:");
GLchar infoLog[1024];
glGetProgramInfoLog(program, 1024, NULL, infoLog);
printf(infoLog);
}
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
// create triangle buffer
/* GLfloat triangleVertices[] =
{ // X Y
-0.25f, 0.6f,
-0.25f, -0.4f,
-0.15f, -0.4f,
-0.15f, 0.6f,
-0.25f, 0.6f,
-0.15f, -0.4f,
0.15f, 0.6f,
0.25f, 0.6f,
0.15f, -0.4f,
0.25f, 0.6f,
0.25f, -0.4f,
0.15f, -0.4f,
-0.25f, 0.15f,
-0.25f, 0.05f,
0.25f, 0.05f,
-0.25f, 0.15f,
0.25f, 0.15f,
0.25f, 0.05f,
-0.25f, -0.5f,
0.25f, -0.5f,
0.25f, -0.6f,
0.25f, -0.6f,
-0.25f, -0.5f,
-0.25f, -0.6f,
}; */
GLfloat cubeVertices[] = {
// Front face (red)
-0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, -0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
// Back face (gree
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
-0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
-0.5f, -0.5f, -0.5f,
// Left face (blu
-0.5f, -0.5f, -0.5f,
-0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
-0.5f, -0.5f, -0.5f,
-0.5f, 0.5f, -0.5f,
-0.5f, 0.5f, 0.5f,
// Right face (yello
0.5f, -0.5f, -0.5f,
0.5f, -0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
0.5f, 0.5f, -0.5f,
0.5f, 0.5f, 0.5f,
0.5f, -0.5f, -0.5f,
// Top face (cya
-0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, -0.5f,
// Bottom face (mage
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, 0.5f,
-0.5f, -0.5f, 0.5f
};
GLuint cubeVertexBufferObject;
glGenBuffers(1, &cubeVertexBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, cubeVertexBufferObject);
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), cubeVertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
/* GLuint triangleVertexBufferObject;
glGenBuffers(1,&triangleVertexBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, triangleVertexBufferObject);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangleVertices), triangleVertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0); */
// create color buffer
/* GLfloat triangleColors[] =
{ // R G B
1.00f, 1.00f, 1.00f,
1.00f, 1.00f, 1.00f,
1.00f, 1.00f, 1.00f,
1.00f, 1.00f, 1.00f,
1.00f, 1.00f, 1.00f,
1.00f, 1.00f, 1.00f
}; */
//color for the cube
GLfloat cubeColors[]=
{
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f,
0.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f
};
GLuint cubeColorBufferObject;
glGenBuffers(1, &cubeColorBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, cubeColorBufferObject);
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), cubeVertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
/* GLuint triangleColorBufferObject;
glGenBuffers(1,&triangleColorBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, triangleColorBufferObject);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangleColors), triangleColors, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0); */
// create vertex array object
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, cubeVertexBufferObject);
glVertexAttribPointer(
0,
3,
GL_FLOAT,
GL_FALSE,
0,
0
);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, cubeColorBufferObject);
glVertexAttribPointer(
1,
3,
GL_FLOAT,
GL_FALSE,
0,
0
);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glViewport(0,0,800,600);
}
void draw(void) {
/* glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program);
glBindVertexArray(vao);
GLfloat modelViewMatrix[16];
GLfloat projectionMatrix[16];
GLint colorUniform = glGetUniformLocation(program, "color");
float red = ((sin((float)(frame-150)/100))+1.0f)/2.0f;
float green = ((sin((float)(frame-100)/120))+1.0f)/2.0f;
float blue = ((sin((float)(frame-150)/140))+1.0f)/2.0f;
glUniform3f(colorUniform, red, green, blue);
GLint positionUniform = glGetUniformLocation(program, "transformMatrix");
GLfloat matrix[16];
identity(matrix);
rotatez(matrix, M_PI*(frame/300.0f));
GLfloat translateMatrix[4] = {sin(frame/100.0f), cos(frame/100.0f), 0.0f, 1.0f};
translate(matrix, translateMatrix);
GLfloat scaleMatrix[4] = {(sin(frame/60.0f)+2.5f)/5, (sin(frame/60.0f)+2.5f)/5, 1.0f, 1.0f};
scale(matrix, scaleMatrix);
glUniformMatrix4fv(positionUniform, 1, GL_FALSE, matrix);
GLint fragColor1Uniform = glGetUniformLocation(program, "fragColor1");
glUniform3f(fragColor1Uniform, 1.0f, 0.0f, 0.0f);
GLint fragColor2Uniform = glGetUniformLocation(program, "fragColor2");
glUniform3f(fragColor2Uniform, 0.0f, 1.0f, 0.0f);
glDrawArrays(GL_TRIANGLES, 0, 104);
frame++; */
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(program);
glBindVertexArray(vao);
// Calculate model-view and projection matrices
GLfloat modelViewMatrix[16];
GLfloat projectionMatrix[16];
//... calculate model-view matrix using rotate, translate, and scale functions...
identity(modelViewMatrix);
rotatez(modelViewMatrix, M_PI*(frame/300.0f));
GLfloat translateMatrix[4] = {sin(frame/100.0f), cos(frame/100.0f), 0.0f, 1.0f};
translate(modelViewMatrix, translateMatrix);
GLfloat scaleMatrix[4] = {(sin(frame/60.0f)+2.5f)/5, (sin(frame/60.0f)+2.5f)/5, 1.0f, 1.0f};
scale(modelViewMatrix, scaleMatrix);
//... calculate projection matrix using perspective function...
perspective(projectionMatrix, 45.0f, 800.0f/600.0f, 0.1f, 100.0f);
// Pass model-view and projection matrices to shader program
GLint modelViewUniform = glGetUniformLocation(program, "modelViewMatrix");
glUniformMatrix4fv(modelViewUniform, 1, GL_FALSE, modelViewMatrix);
GLint projectionUniform = glGetUniformLocation(program, "projectionMatrix");
glUniformMatrix4fv(projectionUniform, 1, GL_FALSE, projectionMatrix);
glDrawArrays(GL_TRIANGLES, 0, 36);
frame++;
}
void framebuffer_size_callback(GLFWwindow *window, int width, int height) {
glViewport(0, 0, width, height);
}
int main(void) {
printf("Hallo!\n");
GLfloat probeMatrix[16];
identity(probeMatrix);
GLfloat eye[3] = {1.0f, 3.0f, 2.0f};
GLfloat center[3] = {2.0f, 2.0f, 2.0f};
GLfloat up[3] = {1.0f, 1.0f, 1.0f};
GLfloat fovy = 10.0f;
GLfloat aspect = 2.0f;
GLfloat near = 2.0f;
GLfloat far = 4.0f;
//lookAt(probeMatrix, eye, center, up );
perspective(probeMatrix, fovy, aspect, near, far);
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow *window = glfwCreateWindow(800, 600, "Computergrafik 1", NULL, NULL);
if (!window) {
printf("Failed to create window\n");
glfwTerminate();
return -1;
}
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwMakeContextCurrent(window);
glewInit();
init();
while (!glfwWindowShouldClose(window)) {
draw();
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
...and I don't understand how. I expected a cube.
Perhaps I do not understand my code, but I think it should work.
Upvotes: -2
Views: 80
Reputation: 20918
Function for computing perspective transform matrix has bug, indices 11 and 14 have to be swapped:
out[9] = 0.0f;
out[10] = (-1) * (far + near) / (far - near);
out[14] = (-2) * far * near / (far - near); // <---
out[12] = 0.0f;
out[13] = 0.0f;
out[11] = -1.0f; // <---
out[15] = 0.0f;
You don't set matrix of view transformation, so default position of eye is (0,0,0)
that points along [0,0,-1]
direction vector.
Becuase we are affected by point 2, your cube has to be shifted towards negative value of Z axis in order to be seen:
//... calculate model-view matrix using rotate, translate, and scale functions...
identity(modelViewMatrix);
//rotatez(modelViewMatrix, M_PI*(frame/300.0f));
GLfloat translateMatrix[4] = {sin(frame/100.0f), cos(frame/100.0f), -20.0f, 1.0f};
translate(modelViewMatrix, translateMatrix);
//GLfloat scaleMatrix[4] = {(sin(frame/60.0f)+2.5f)/5, (sin(frame/60.0f)+2.5f)/5, 1.0f, 1.0f};
//scale(modelViewMatrix, scaleMatrix);
as you can see, Z value in translation is set to -20.
You may ask why I left only translation matrix. Because if your intention was to combine scale, translate and rotation as composition you have to fix all mentioned functions and remove from them identity
. For example scale
function doesn't multiply modelViewMatrix
but just set scale matrix into modelViewMatrix
.
Vertex shader code has typos:
uniform mat4 transformMatrix;
should be:
uniform mat4 modelViewMatrix;
After applying all above fixes, you will get:
Upvotes: 2