I've modified my original code (previous post) to use two textures. Here they are:
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "support.h"
using namespace std;
GLuint *images;
GLubyte *image;
GLuint texture1=0;
GLuint texture2=0;
GLuint LoadTexture(int width, int height, char *fName);
int n=200;
int m=200;
void showPictureW();
void showPictureR();
float rX=0;
float rY=0;
float rZ=0;
float tX=0;
float tY=0;
float tZ=-3.5;
float nr = -5.0;
float fr = -4.0;
float tpx = 1.0;
float tpy = 1.0;
float btx = -1.0;
float bty = -1.0;
float dZ =-2.0;
void showPictureW()
{
/* clear all pixels */
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3d(1,1,1);
//face 1
glBegin( GL_POLYGON );
glTexCoord2d(1.0,1.0); glVertex3d(-1.0,1.0,-2.0);
glTexCoord2d(1.0,0.0); glVertex3d(-1,-1.0,-2.0);
glTexCoord2d(0.0,0.0); glVertex3d(1.0,-1.0,-2.0);
glEnd();
//face 2
glBegin( GL_POLYGON );
glTexCoord2d(0.0,0.0); glVertex3d(1.0,-1.0,-2.0);
glTexCoord2d(0.0,1.0); glVertex3d(1.0,1.0,-2.0);
glTexCoord2d(1.0,1.0); glVertex3d(-1.0,1.0,-2.0);
glEnd();
}
void showPictureR()
{
//clear all pixels
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3d(1,1,1);
//face 1
glBegin( GL_POLYGON );
glTexCoord2d(1.0,1.0); glVertex3d(-1.2,1.0,-2.0);
glTexCoord2d(1.0,0.0); glVertex3d(0.0,1.0,-2.0);
glTexCoord2d(0.0,0.0); glVertex3d(0.0,2.0,-2.0);
glEnd();
//face 2
glBegin( GL_POLYGON );
glTexCoord2d(0.0,0.0); glVertex3d(0.0,2.0,-2.0);
glTexCoord2d(0.0,1.0); glVertex3d(0.0,1.0,-2.0);
glTexCoord2d(1.0,1.0); glVertex3d(1.2,1.0,-2.0);
glEnd();
}
static void resize(int width, int height)
{
const float ar = (float) width / (float) height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-ar, ar, -1.0, 1.0, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity() ;
}
static void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3d(1,0,0);
glEnable( GL_TEXTURE_2D );
glBindTexture( GL_TEXTURE_2D, texture1 );
glPushMatrix();
glTranslated(0,0,0);
glRotated(rX,0,0,1);
glRotated(rY,0,1,0);
glRotated(rZ,1,0,0);
showPictureW();
glPopMatrix();
glBindTexture( GL_TEXTURE_2D, texture2 );
glPushMatrix();
glTranslated(0,0,0);
glRotated(rX,0,0,1);
glRotated(rY,0,1,0);
glRotated(rZ,1,0,0);
showPictureR();
glPopMatrix();
glutSwapBuffers();
}
static void key(unsigned char key, int x, int y)
{
switch (key)
{
case 27 :
case 'q':
exit(0);
break;
case '+':
break;
...
}
glutPostRedisplay();
}
static void idle(void)
{
glutPostRedisplay();
}
const GLfloat light_ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
const GLfloat light_diffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat light_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat light_position[] = { 2.0f, 5.0f, 5.0f, 0.0f };
const GLfloat mat_ambient[] = { 0.7f, 0.7f, 0.7f, 1.0f };
const GLfloat mat_diffuse[] = { 0.8f, 0.8f, 0.8f, 1.0f };
const GLfloat mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
const GLfloat high_shininess[] = { 100.0f };
/* Program entry point */
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitWindowSize(640,480);
glutInitWindowPosition(10,10);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow("FreeGLUT Shapes");
glutReshapeFunc(resize);
glutDisplayFunc(display);
glutKeyboardFunc(key);
glutIdleFunc(idle);
glClearColor(1,1,1,1);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess);
texture1 = LoadTexture( 200, 200, "wall.ppm" );
texture2 = LoadTexture( 200, 200, "roof.ppm" );
glutMainLoop();
return EXIT_SUCCESS;
}
GLuint LoadTexture(int width, int height, char *fName)
{
FILE *fd;
int k, nm;
int i;
char bc[71];
float s;
unsigned int red, green, blue;
char c;
fd = fopen(fName,"r");
fscanf(fd,"%[^\n]",bc); // reads data from stream
printf("Nilai %s \n\n",bc);
if(bc[0]!='P'|| bc[1]!='3')
{
printf("%s Not a PPM file\n",bc);
exit(0);
}
printf("%s is a PPM file\n",bc);
fscanf(fd,"%s",bc);
printf("line 1 %s \n",bc);
fscanf(fd,"%s",bc);
printf("line 2 %s \n",bc);
fscanf(fd,"%s",bc);
printf("line 3 %s \n",bc);
fscanf(fd,"%s",bc);
printf("line 4 %s \n",bc);
fscanf(fd,"%c",&c);
ungetc(c,fd);
fscanf(fd,"%d %d %d", &n,&m,&k);
nm = n*m;
images = new GLuint[3*sizeof(GLuint)*nm];
for (i=0;i<nm;i++)
{
fscanf(fd,"%u %u %u", &red, &green, &blue);
images[3*nm-3*i-3] = red;
images[3*nm-3*i-2] = green;
images[3*nm-3*i-1] = blue;
}
int totSize = 3*nm;
int tot=0;
for(i=0;i<nm;i++)
{
tot++;
}
image = new BYTE[width*height*3*sizeof(BYTE)];
int nmOne = width*height;
for(int i=0;i<nmOne*3;i++)//copy each value 3 times
{
image[i] = (GLubyte)images[i];
image[i] = (GLubyte)images[i];
image[i] = (GLubyte)images[i];
}
bool wrap = true;
GLuint texture = 0;
glGenTextures( 1, &texture );
// select our current texture
glBindTexture( GL_TEXTURE_2D, texture );
// select modulate to mix texture with color for shading
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
// when texture area is small, bilinear filter the closest mipmap
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
// when texture area is large, bilinear filter the first mipmap
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
// if wrap is true, the texture wraps over at the edges (repeat)
// ... false, the texture ends at the edges (clamp)
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap ? GL_REPEAT : GL_CLAMP );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,wrap ? GL_REPEAT : GL_CLAMP );
// build our texture mipmaps
gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, height,
GL_RGB, GL_UNSIGNED_BYTE, image );
return texture;
}
My problem is that it won't load both textures at once. I've tried using one at a time and they're okay. But with the above code only the second texture ("roof.ppm") appears. I found the code below in another post which seems quite similar to my problem but I'm not sure how to use it.
void DrawFrame()
{
...
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluOrtho2D(0, this.Width, 0, this.Height);
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
// "camera" transform(s)
foreach object
{
glPushMatrix();
// per-object matrix transform(s)
// draw object
glPopMatrix();
}
}
You do call
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
in both of your showPictureW and showPictureR functions, so it should not surprise you that only the effects last of these calls can be seen in the end.
Related
I have recently started learning opengl on learnopengl.com. I am the chapter about textures. I have managed to load 2 textures however when I tell opengl to render the texture currently bound to GL_TEXTURE0 it instead draws the texture currently bound to GL_TEXTURE1.
My main.c file looks like this:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "glad/glad.h"
#include "GLFW/glfw3.h"
#include "stb/stb_image_init.h"
#define WIDTH 1080
#define HEIGHT 720
typedef unsigned int uint;
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void process_input(GLFWwindow* window);
void check_shader_compilation(GLuint shader_object, GLenum shader_type);
void check_shader_linking(GLuint shader_program);
char* get_shader_code(const char* path);
int main(void) {
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "Triangle", NULL, NULL);
if (window == NULL) {
printf("Unable to create glfw window!\n");
return -1;
}
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
printf("Couldn't initialize glad!\n");
return -1;
}
glViewport(0, 0, WIDTH, HEIGHT);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
char* vertex_shader_code = get_shader_code("shaders/vertex.glsl");
GLuint vertex_shader_object = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader_object, 1, &vertex_shader_code, NULL);
glCompileShader(vertex_shader_object);
check_shader_compilation(vertex_shader_object, GL_VERTEX_SHADER);
free(vertex_shader_code);
char* fragment_shader_code = get_shader_code("shaders/fragment.glsl");
GLuint fragment_shader_object = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader_object, 1, &fragment_shader_code, NULL);
glCompileShader(fragment_shader_object);
check_shader_compilation(fragment_shader_object, GL_FRAGMENT_SHADER);
free(fragment_shader_code);
uint shader_program = glCreateProgram();
glAttachShader(shader_program, vertex_shader_object);
glAttachShader(shader_program, fragment_shader_object);
glLinkProgram(shader_program);
glUseProgram(shader_program);
check_shader_linking(shader_program);
float rectangle_data[] = {
// Coords Colors Texture coords
-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, // Bottom Left
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // Bottom Right
-0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, // Top Left
0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // Top Right
};
unsigned int indicies[] = {
0, 2, 3,
0, 1, 3,
};
uint vao, vbo, ebo;
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glGenBuffers(1, &ebo);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ARRAY_BUFFER, sizeof(rectangle_data), rectangle_data, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indicies), indicies, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float)*8, (void*)0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float)*8, (void*)(sizeof(float)*3));
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(float)*8, (void*)(sizeof(float)*6));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
float border_color[] = { 1.0f, 0.0f, 0.0f, 1.0f };
uint texture_buffer, texture2_buffer;
glGenBuffers(1, &texture_buffer);
glBindTexture(GL_TEXTURE_2D, texture_buffer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
stbi_set_flip_vertically_on_load(true);
int width = 0, height = 0, n_channels = 0;
unsigned char* texture_image = stbi_load("assets/textures/luffy.jpg", &width, &height, &n_channels, 0);
if (texture_image) {
printf("Loaded texture0!\n");
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, texture_image);
glGenerateMipmap(GL_TEXTURE_2D);
}
else {
printf("Couldn't find the image for the texture\n");
exit(-1);
}
stbi_image_free(texture_image);
glGenBuffers(1, &texture2_buffer);
glBindTexture(GL_TEXTURE_2D, texture2_buffer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
int t2_width = 0, t2_height = 0, t2_n_channels = 0;
unsigned char* texture2_image = stbi_load("assets/textures/face.png", &t2_width, &t2_height, &t2_n_channels, 0);
if (texture2_image) {
printf("Loaded texture1!\n");
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, t2_width, t2_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture2_image);
glGenerateMipmap(GL_TEXTURE_2D);
}
else {
printf("Couldn't find the image for texture2\n");
exit(-1);
}
stbi_image_free(texture2_image);
glUseProgram(shader_program);
glUniform1i(glGetUniformLocation(shader_program, "luffy"), 0);
glUniform1i(glGetUniformLocation(shader_program, "face"), 1);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
while (!glfwWindowShouldClose(window)) {
process_input(window);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture_buffer);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture2_buffer);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glfwPollEvents();
glfwSwapBuffers(window);
}
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(1, &vbo);
glDeleteBuffers(1, &ebo);
glDeleteShader(vertex_shader_object);
glDeleteShader(fragment_shader_object);
glDeleteProgram(shader_program);
glfwTerminate();
return 0;
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
glViewport(0, 0, width, height);
}
void process_input(GLFWwindow* window) {
if (glfwGetKey(window, GLFW_KEY_Q) == true) {
glfwSetWindowShouldClose(window, true);
}
}
void check_shader_compilation(GLuint shader_object, GLenum shader_type) {
char* print_shader_type;
switch (shader_type) {
case GL_VERTEX_SHADER:
print_shader_type = "vertex";
break;
case GL_FRAGMENT_SHADER:
print_shader_type = "fragment";
break;
default:
printf("Cannot check for shader compilation, the shader_type is not GL_VERTEX_SHADER or GL_FRAGMENT_SHADER!\n");
exit(-1);
}
int shader_status;
glGetShaderiv(shader_object, GL_COMPILE_STATUS, &shader_status);
if (!shader_status) {
int message_length;
GLchar error[1024];
glGetShaderInfoLog(shader_object, 1024, &message_length, error);
printf("Could not compile the %s shader: \n %s\n", print_shader_type, error);
exit(-1);
}
else {
printf("Compiled the %s shader!\n", print_shader_type);
}
}
void check_shader_linking(GLuint shader_program) {
int linking_status;
glGetProgramiv(shader_program, GL_LINK_STATUS, &linking_status);
if (!linking_status) {
int message_length;
GLchar error[1024];
glGetProgramInfoLog(shader_program, 1024, &message_length, error);
printf("Could not link the shader program:\n %s\n", error);
exit(-1);
}
else {
printf("Linked the shader program!\n");
}
}
char* get_shader_code(const char* path) {
FILE* shader_file = fopen(path, "rb");
if (!shader_file) {
printf("Incorrect file path for shader: %s\n", path);
exit(-1);
}
fseek(shader_file, 0, SEEK_END);
int file_size = ftell(shader_file);
rewind(shader_file);
char* shader_code = malloc(file_size + 1);
shader_code[file_size] = '\0';
fread(shader_code, sizeof(char), file_size, shader_file);
return shader_code;
}
My Vertex shader is:
#version 330
layout (location = 0) in vec3 pos;
layout (location = 1) in vec3 colors;
layout (location = 2) in vec2 texCoords;
out vec3 vertex_colors;
out vec2 tex_coords;
void main() {
gl_Position = vec4(pos.x, pos.y, pos.z, 1.0);
vertex_colors = colors;
tex_coords = texCoords;
}
And my fragment shader is:
#version 330 core
out vec4 fragColor;
in vec3 vertex_colors;
in vec2 tex_coords;
uniform sampler2D luffy;
uniform sampler2D face;
void main() {
fragColor = texture(luffy, tex_coords);
}
Whenever I run the program, it texture it uses is the image in face.png, whereas I told it to use the image in luffy.jpg.
You never create any texture objects:
glGenBuffers(1, &texture_buffer);
glBindTexture(GL_TEXTURE_2D, texture_buffer);
glGenBuffers is for buffer objects, not for texture objects. You have to use glGenTextures. (Also calling your variable texture_buffer here is very confusing. There are buffer textures in the GL, but you're not using those here).
And since you use a core profile, the glBindTexture() call will just generate a GL error and have no other effect, becuase the object name you try to bind never was generated by glGenTextures. So in effect, you are working with texture object 0 here, and load both images to that texture object, with the latter overwriting the former. In a core profiler, using texture object 0 actually shouldn't work, but many drivers still allow it (as it was allowed in legacy GL), so that you actually see any texture at all is not guaranteed either.
I am following the tutorials on learnopengl.com and I have come across an issues. I am writing my program in C rather than C++ and am using the linmath library for my matrix transformation and I have the files shader.c and texture.c. I believe that the issue is with my matrix transformation but I can't figure out where I've gone wrong. The program runs and it compiles, the window is created and the background colour is correct however the object does not show.
Here is the source:
#include <stdio.h>
#include <stdlib.h>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "linmath.h"
#include "shader.h"
#include "texture.h"
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
int main(){
// glfw: initialize and configure
// ------------------------------
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X
// glfw window creation
// --------------------
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
if (window == NULL){
printf("Failed to create GLFW window");
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
printf("Failed to initialize GLAD");
return -1;
}
Shader ourShader;
ourShader.ID = loadShader("3.3.shader.vs", "3.3.shader.fs");
// set up vertex data (and buffer(s)) and configure vertex attributes
// ------------------------------------------------------------------
float vertices[] = {
// positions // colors // texture coords
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, // top right
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f // top left
};
unsigned int indices[] = {
0, 1, 3, // first triangle
1, 2, 3 // second triangle
};
unsigned int VBO, VAO, EBO;
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, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// texture coord attribute
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
Texture tex1 = loadTexture("container.jpg");
Texture tex2 = loadTexture("awesomeface.png");
// tell opengl for each sampler to which texture unit it belongs to (only has to be done once)
// -------------------------------------------------------------------------------------------
useShader(ourShader.ID);
setIntShader("texture1", 0, ourShader.ID);
setIntShader("texture2", 1, ourShader.ID);
// render loop
// -----------
while (!glfwWindowShouldClose(window))
{
// input
// -----
processInput(window);
// render
// ------
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// bind textures on corresponding texture units
bindTexture(tex1, GL_TEXTURE0);
bindTexture(tex2, GL_TEXTURE1);
// activate shader
useShader(ourShader.ID);
// create transformations
mat4x4 model;
mat4x4 m;
mat4x4 view;
mat4x4 projection;
mat4x4_rotate(model, m, 1.0f, 0.0f, 0.0f, -0.95993f);
mat4x4_translate(view, 0.0f, 0.0f, -3.0f);
mat4x4_perspective(projection, 0.785f, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
// pass them to the shaders
setMat4Shader("model", model, ourShader.ID);
setMat4Shader("view", view, ourShader.ID);
setMat4Shader("projection", projection, ourShader.ID);
// render container
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// -------------------------------------------------------------------------------
glfwSwapBuffers(window);
glfwPollEvents();
}
// optional: de-allocate all resources once they've outlived their purpose:
// ------------------------------------------------------------------------
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
// glfw: terminate, clearing all previously allocated GLFW resources.
// ------------------------------------------------------------------
glfwTerminate();
return 0;
}
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, width, height);
}
void processInput(GLFWwindow *window)
{
if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
shader.c
#include "shader.h"
GLuint loadShader(const char * vertex_file_path,const char * fragment_file_path){
// Create the shaders
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
// Read the Vertex Shader code from the file
char* VertexShaderCode;
FILE * vertexFile = fopen(vertex_file_path, "r");
if( vertexFile == NULL ){
printf("Impossible to open the file !\n");
return LOAD_FAILURE;
}
long vertex_file_size;
fseek(vertexFile, 0, SEEK_END);
vertex_file_size = ftell(vertexFile);
rewind(vertexFile);
VertexShaderCode = malloc((vertex_file_size + 1) * (sizeof(char)));
fread(VertexShaderCode, sizeof(char), vertex_file_size, vertexFile);
fclose(vertexFile);
VertexShaderCode[vertex_file_size] = 0;
// Read the Fragment Shader code from the file
char* FragmentShaderCode;
FILE * fragmentFile = fopen(fragment_file_path, "r");
if( fragmentFile == NULL ){
printf("Impossible to open the file !\n");
return LOAD_FAILURE;
}
long fragment_file_size;
fseek(fragmentFile, 0, SEEK_END);
fragment_file_size = ftell(fragmentFile);
rewind(fragmentFile);
FragmentShaderCode = malloc((fragment_file_size + 1) * (sizeof(char)));
fread(FragmentShaderCode, sizeof(char), fragment_file_size, fragmentFile);
fclose(fragmentFile);
FragmentShaderCode[fragment_file_size] = 0;
const char* vsCode = VertexShaderCode;
const char* fsCode = FragmentShaderCode;
// 2. compile shaders
unsigned int vertex, fragment;
int success;
char infoLog[512];
// vertex shader
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vsCode, NULL);
glCompileShader(vertex);
checkCompileErrors(vertex, "VERTEX");
// fragment Shader
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fsCode, NULL);
glCompileShader(fragment);
checkCompileErrors(fragment, "FRAGMENT");
// shader Program
GLuint ID = glCreateProgram();
glAttachShader(ID, vertex);
glAttachShader(ID, fragment);
glLinkProgram(ID);
checkCompileErrors(ID, "PROGRAM");
// delete the shaders as they're linked into our program now and no longer necessery
glDeleteShader(vertex);
glDeleteShader(fragment);
return ID;
}
void useShader(unsigned int ID){
glUseProgram(ID);
}
void setBoolShader(const char * name, int value, unsigned int ID)
{
glUniform1i(glGetUniformLocation(ID, name), value);
}
void setIntShader(const char * name, int value, unsigned int ID)
{
glUniform1i(glGetUniformLocation(ID, name), value);
}
void setFloatShader(const char * name, float value, unsigned int ID)
{
glUniform1f(glGetUniformLocation(ID, name), value);
}
void setMat4Shader(const char * name, mat4x4 mat, unsigned int ID)
{
glUniformMatrix4fv(glGetUniformLocation(ID, name), 1, GL_FALSE, *mat);
}
void checkCompileErrors(GLuint shader, char type[])
{
GLint success;
GLchar infoLog[1024];
if(strncmp(type, "PROGRAM", 7) != 0)
{
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(shader, 1024, NULL, infoLog);
printf("ERROR::SHADER_COMPILATION_ERROR of type: %s \n %s \n", type, infoLog);
}
}
else
{
glGetProgramiv(shader, GL_LINK_STATUS, &success);
if(!success)
{
glGetProgramInfoLog(shader, 1024, NULL, infoLog);
printf("ERROR::SHADER_COMPILATION_ERROR of type: %s \n %s \n", type, infoLog);
}
}
}
texture.c
#include "texture.h"
Texture loadTexture(const char* path){
unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
// set the texture wrapping/filtering options (on the currently bound texture object)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//load texture
int width, height, nrChannels;
unsigned char *data = SOIL_load_image(path, &width, &height, &nrChannels, SOIL_LOAD_RGB);
if(data){
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
} else{
printf("Failed to load Image");
}
SOIL_free_image_data(data);
Texture t;
t.ID = texture;
t.path = path;
return t;
}
void bindTexture(Texture texture, GLenum unit){
// bind textures on corresponding texture units
glActiveTexture(unit);
glBindTexture(GL_TEXTURE_2D, texture.ID);
}
vertex shader
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
out vec2 TexCoord;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0);
TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}
Fragment Shader
#version 330 core
out vec4 FragColor;
in vec2 TexCoord;
// texture samplers
uniform sampler2D texture1;
uniform sampler2D texture2;
void main()
{
// linearly interpolate between both textures (80% container, 20% awesomeface)
FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2);
}
I am stuck trying to get this code to work in Visual Studio 2012 using glut. It renders a 10/10 3D grid but it will not respond to my input from the keyboard. I am trying to get the camera to rotate around the origin when i hit the left arrow key.
// This example shows how to create a camera for 3D graphics.
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#include <iostream>
#include <cmath>
#include <math.h>
using namespace std;
int g_winWidth = 1024;
int g_winHeight = 512;
bool keyStatus[256];
float angle = 0.0f; //angle for rotating camera
float beginning_angle = 0.0f;
float cx = 10.0, cy = 10.0, cz = -10.0;
void initialGL()
{
glEnable(GL_DEPTH_TEST);
glClearColor (1.0f, 1.0f, 1.0f, 0.0f);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode (GL_MODELVIEW);
glLoadIdentity();
}
//initialize the keyboard keys
void initialization()
{
for(int i =0; i<256; i++)
keyStatus[i] = false;
}
//function to draw the colored x,y, and z axis
void drawCS()
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glScalef(10.0f, 10.0f, 10.0f);
glLineWidth(2.5f);
glBegin(GL_LINES);
//axis x
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.3f, 0.0f, 0.0f);
//text x
glVertex3f(0.4f, 0.05f, 0.0f);
glVertex3f(0.5f, -0.05f, 0.0f);
glVertex3f(0.4f, -0.05f, 0.0f);
glVertex3f(0.5f, 0.05f, 0.0f);
//axis y
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.3f, 0.0f);
//text y
glVertex3f(0.0f, 0.5f, 0.0f);
glVertex3f(0.0f, 0.4f, 0.0f);
glVertex3f(-0.05f, 0.55f, 0.0f);
glVertex3f(0.0f, 0.5f, 0.0f);
glVertex3f(0.05f, 0.55f, 0.0f);
glVertex3f(0.0f, 0.5f, 0.0f);
//axis z
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, 0.0f);
glVertex3f(0.0f, 0.0f, 0.3f);
//text z
glVertex3f(-0.025f, 0.025f, 0.4f);
glVertex3f(0.025f, 0.025f, 0.4f);
glVertex3f(0.025f, 0.025f, 0.4f);
glVertex3f(-0.025f, -0.025f, 0.4f);
glVertex3f(-0.025f, -0.025f, 0.4f);
glVertex3f(0.025f, -0.025f, 0.4f);
glEnd();
glLineWidth(1.0f);
glPopMatrix();
}
//function to draw the grid
void drawGrid()
{
int size = 10; // determining the grid size and the numbers of cells
if(size%2 != 0) ++size;
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
//glScalef(30.0f, 30.0f, 30.0f);
glBegin(GL_LINES);
for (int i =0; i<size+1; i++) {
if((float)i == size/2.0f) {
glColor3f(0.0f, 0.0f, 0.0f);
} else {
glColor3f(0.8f, 0.8f, 0.8f);
}
glVertex3f(-size/2.0f, 0.0f, -size/2.0f+i);
glVertex3f(size/2.0f, 0.0f, -size/2.0f+i);
glVertex3f(-size/2.0f+i, 0.0f, -size/2.0f);
glVertex3f(-size/2.0f+i, 0.0f, size/2.0f);
}
glEnd();
glPopMatrix();
}
//function to display everything that is happening in window
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
drawGrid();// call to function to draw the grid
drawCS();//call to function to draw the x,y,z axis
glutSwapBuffers();
}
void reshape(int w, int h)
{
g_winWidth = w;
g_winHeight = h;
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//this function sets the initial position of the camera in 3D space
/*
Need to find a way to rotate around the origin from left to right
*/
gluLookAt( cx, cy, cz, //camera position
0.0f, 0.0f, 0.0f, //what camera looks at
0.0f, 1.0f, 0.0f); //
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, g_winWidth/g_winHeight, 0.1, 100);//specifies the view for the scene
glViewport(0, 0, w, h);
//angle += 0.1f;
}
//keyboard function for the exit key
void keyboard(unsigned char key, int x, int y)
{
keyStatus[key] = true;
switch (key) {
case 27:
exit(0);
break;
default:
break;
}
}
//sets the keyboard callback to the current window
void keyboardUp(unsigned char key, int x, int y)
{
keyStatus[key] = false;
}
//function for arrow keys output
void processSpecialKeys(int key, int xx, int yy) {
switch(key) {
case GLUT_KEY_LEFT :
//What the left arrow key does
angle -= 0.01f;
cx = sin(angle);
cz = -cos(angle);
break;
case GLUT_KEY_RIGHT :
//What the right arrow key does
break;
case GLUT_KEY_UP :
//What the up arrow key does
break;
case GLUT_KEY_DOWN :
//What the down arrow key does
break;
}
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(g_winWidth, g_winHeight);
glutInitWindowPosition(0, 0);
glutCreateWindow("Camera");
initialGL();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutIdleFunc(display);
glutKeyboardFunc(keyboard);
glutKeyboardUpFunc(keyboardUp);
glutSpecialFunc(processSpecialKeys);
glEnable(GL_DEPTH_TEST);
initialization();
glutMainLoop();
return 1;//changed from EXIT_SUCCESS
}
I'm trying to render a simple (10x3x10 in size) room using OpenGL and GLUT, written in C.
I'd like to create a simple statinary spotlight, while i can move around in the room.
(The ultimate goal is to make a spotlight coming from a lamp at the ceiling)
The problem is the light changes when i move the camera around.
I'm calling the following function from main():
void init() {
glEnable(GL_TEXTURE_2D);
loadTexture(); // loading some textures using SOIL
loadModels(); // loading some OBJ models
glShadeModel(GL_SMOOTH);
glEnable(GL_NORMALIZE);
glEnable(GL_AUTO_NORMAL);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glClearDepth(1);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glDepthFunc(GL_LEQUAL);
glClearColor(0, 0, 0, 1);
}
The function i pass to glutDisplayFunc():
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
initLight();
gluLookAt(x, 1.5f, z, x + vX, 1.5f, z + vZ, 0.0f, 1.5f, 0.0f);
// ...
// drawing the ground, ceiling and the walls
// no matrix transformations here, just simple glVertex () calls
// ...
glPushMatrix();
// drawing a table
glTranslatef(5, 0.842843, 5);
glBindTexture(GL_TEXTURE_2D, texture[1]);
draw_model(&modelTable);
// drawing some chairs
glTranslatef(0, -0.312053, chair1Position);
glBindTexture(GL_TEXTURE_2D, texture[2]);
draw_model(&modelChair1);
glTranslatef(0, 0, chair2Position);
draw_model(&modelChair2);
glPopMatrix();
glutSwapBuffers();
}
And the initLight() function:
void initLight() {
// i would like the light to originate from an upper corner
// directed to the opposing lower corner (across the room basically)
GLfloat lightPosition[] = { 10, 3, 0, 1 };
GLfloat lightDirection[] = { 0, 0, 10, 0 };
GLfloat ambientLight[] = { 0.3, 0.3, 0.3, 1 };
GLfloat diffuseLight[] = { 1, 1, 1, 1 };
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 180);
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 64);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, lightDirection);
}
I was told this problem could be solved by the proper positioning of the glPushMatrix() and glPopMatrix() calls.
Wherever i put them, the light either keeps changing when i'm moving the camera or i got no light at all. I just cannot figure it out.
What would be a proper solution here?
Thanks in advance.
EDIT:
I've moved the initLight() call to after the gluLookAt() call as #derhass suggested below.
The light is still changing when i'm moving around.
There are two screenshots below.
On the first one the light is not even visible. When i turn slightly to the right, it appears.
EDIT2:
The full (stripped down) source code:
#include <GL/glut.h>
#include <SOIL/SOIL.h>
#include <math.h>
GLfloat lightPosition[] = { 10, 3, 0, 1 };
GLfloat lightDirection[] = { 0, 0, 10, 0 };
GLfloat diffuseLight[] = { 0, 1, 0, 1 };
GLfloat ambientLight[] = { 0.2, 0.2, 0.2, 1 };
float x = 1.0f, z = 5.0f;
float vX = 1.0f, vZ = 0.0f;
float angle = 1.5f;
int windowWidth = 1024;
int windowHeight = 768;
char* textureFiles[13] = { "floortexture.png", "tabletexture.png",
"chairtexture.png", "orange.png", "helptexture.png",
"fridgetexture.png", "oven.png", "yellow.png", "dishwasher.png",
"metallic.png", "cabinet.png", "wood.png", "cabinet2.png" };
GLuint texture[13];
void loadTexture() {
for (int i = 0; i < 13; i++) {
texture[i] = SOIL_load_OGL_texture(textureFiles[i], SOIL_LOAD_RGBA,
SOIL_CREATE_NEW_ID, 0);
glBindTexture(GL_TEXTURE_2D, texture[i]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
}
void init() {
glEnable(GL_TEXTURE_2D);
loadTexture();
glShadeModel(GL_SMOOTH);
glEnable(GL_NORMALIZE);
glEnable(GL_AUTO_NORMAL);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glClearDepth(1);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glClearColor(0, 0, 0, 1);
}
void processSpecialKeys(int key, int xx, int yy) {
float moveFraction = 0.2f;
float angleFraction = 0.1f;
switch (key) {
case GLUT_KEY_LEFT:
angle -= angleFraction;
vX = sin(angle);
vZ = -cos(angle);
break;
case GLUT_KEY_RIGHT:
angle += angleFraction;
vX = sin(angle);
vZ = -cos(angle);
break;
case GLUT_KEY_UP:
x += vX * moveFraction;
z += vZ * moveFraction;
if (x < 1) {
x = 1;
}
if (z < 1) {
z = 1;
}
if (x > 9) {
x = 9;
}
if (z > 9) {
z = 9;
}
break;
case GLUT_KEY_DOWN:
x -= vX * moveFraction;
z -= vZ * moveFraction;
if (x < 1) {
x = 1;
}
if (z < 1) {
z = 1;
}
if (x > 9) {
x = 9;
}
if (z > 9) {
z = 9;
}
break;
}
}
void initLight() {
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 180);
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 128);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, lightDirection);
}
void renderWalls() {
// floor
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(0.0f, 0.0f, 0.0f);
glTexCoord2f(0, 8);
glVertex3f(0.0f, 0.0f, 10.0f);
glTexCoord2f(8, 8);
glVertex3f(10.0f, 0.0f, 10.0f);
glTexCoord2f(8, 0);
glVertex3f(10.0f, 0.0f, 0.0f);
glEnd();
// walls
glBindTexture(GL_TEXTURE_2D, texture[3]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// first wall
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(0.0f, 0.0f, 0.0f);
glTexCoord2f(0, 1);
glVertex3f(0.0f, 3.0f, 0.0f);
glTexCoord2f(1, 1);
glVertex3f(10.0f, 3.0f, 0.0f);
glTexCoord2f(1, 0);
glVertex3f(10.0f, 0.0f, 0.0f);
glEnd();
// second wall
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(10.0f, 0.0f, 0.0f);
glTexCoord2f(0, 1);
glVertex3f(10.0f, 3.0f, 0.0f);
glTexCoord2f(1, 1);
glVertex3f(10.0f, 3.0f, 10.0f);
glTexCoord2f(1, 0);
glVertex3f(10.0f, 0.0f, 10.0f);
glEnd();
// third wall
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(10.0f, 0.0f, 10.0f);
glTexCoord2f(0, 1);
glVertex3f(10.0f, 3.0f, 10.0f);
glTexCoord2f(1, 1);
glVertex3f(0.0f, 3.0f, 10.0f);
glTexCoord2f(1, 0);
glVertex3f(0.0f, 0.0f, 10.0f);
glEnd();
// fourth wall
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(0.0f, 0.0f, 0.0f);
glTexCoord2f(0, 1);
glVertex3f(0.0f, 3.0f, 0.0f);
glTexCoord2f(1, 1);
glVertex3f(0.0f, 3.0f, 10.0f);
glTexCoord2f(1, 0);
glVertex3f(0.0f, 0.0f, 10.0f);
glEnd();
// ceiling
glBindTexture(GL_TEXTURE_2D, texture[7]);
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex3f(0.0f, 3.0f, 0.0f);
glTexCoord2f(0, 1);
glVertex3f(10.0f, 3.0f, 0.0f);
glTexCoord2f(1, 1);
glVertex3f(10.0f, 3.0f, 10.0f);
glTexCoord2f(1, 0);
glVertex3f(0.0f, 3.0f, 10.0f);
glEnd();
}
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt(x, 1.5f, z, x + vX, 1.5f, z + vZ, 0.0f, 1.5f, 0.0f);
initLight();
renderWalls();
glutSwapBuffers();
}
void changeWindowSize(int width, int height) {
if (height == 0) {
height = 1;
}
float ratio = 1.0 * width / height;
windowWidth = width;
windowHeight = height;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, width, height);
gluPerspective(45.0f, ratio, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowPosition(0, 0);
glutInitWindowSize(windowWidth, windowHeight);
glutCreateWindow("Kitchen");
init();
glutDisplayFunc(display);
glutReshapeFunc(changeWindowSize);
glutIdleFunc(display);
glutSpecialFunc(processSpecialKeys);
glutMainLoop();
return 0;
}
Your light is stationary - but to the camera.
Fixed-function OpenGL does all the lighting calculations in eye space. At the moment you specify the GL_POSITION of a light, it is transformed according to the current modelView matrix at the time of the call, to get the eye space position. Since modelView is set to identity, it will always set the light to the given eye-space location - no matter where you later place the camera.
To fix this, just move initLight() after the gluLookAt.
However. You should not be doing this at all. You are using deprecated OpenGL features which you shouldn't use since a decade now. In modern GL, that functionality is completely removed. So if you are learning OpenGL in 2016, do yourself a favour and forget about that old cruft, and just learn shaders directly.
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);