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 trying to make a background using SOIL_load_OGL_texture but when I added my 3D models the texture disappeared. The code for 3D models were separated from the texture code but when I combine it, the background becomes black and my 3D models is facing back. Is the problem here because of the coordination?
I expect the output would be the 3D models facing front and it is in front of the texture.
#include <stdlib.h>
#include <stdio.h>
#include <GL/glut.h>
#include "SOIL2.h"
GLuint myTexture;
const GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
const GLfloat mat_diffuse[] = { 0.8f, 0.8f, 0.8f, 1.0f };
static int head = 0, rear = -90, lear = -90, body = 0, lleg = -90, rleg = -90, ball = 0, stage = 0;
GLfloat ballRadius = 0.1f;
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3d(0.5, 0.85, 0.9); // head
glPushMatrix();
glTranslated(0, 0.25, 0.15);
glRotated((GLfloat)head, 0, 1, 0);
glutSolidSphere(0.2, 40, 50);
glPopMatrix();
glPushMatrix(); //ear
glTranslated(0.11, 0.3, 0.18);
glRotated((GLfloat)rear, 1, 0, 0);
glutSolidCone(0.08, 0.2, 16, 16);
glPopMatrix();
glPushMatrix(); //ear
glTranslated(-0.11, 0.3, 0.18);
glRotated((GLfloat)lear, 1, 0, 0);
glutSolidCone(0.08, 0.2, 16, 16);
glPopMatrix();
glColor3d(0.0, 0.0, 0.0); //eyes
glPushMatrix();
glTranslated(0.07, 0.3, 0.33);
glRotated(-5, 0, 0, 1);
glScalef(0.5, 0.1, 0.1);
glutSolidCube(0.1);
glPopMatrix();
glPushMatrix(); //eyes
glTranslated(-0.07, 0.3, 0.33);
glRotated(-5, 0, 0, -1);
glScalef(0.5, 0.1, 0.1);
glutSolidCube(0.1);
glPopMatrix();
glPushMatrix(); //mouth
glTranslated(0.0, 0.25, 0.35);
glRotated(0, 0, 0, 0);
glScalef(1, 0.1, 0.1);
glutSolidCube(0.1);
glPopMatrix();
glColor3d(1.0, 1.0, 1.0);
glPushMatrix(); // teeth
glTranslated(-0.045, 0.255, 0.34);
glRotated(-90, 1, 0, 0);
glutSolidCone(0.01, 0.02, 16, 16);
glPopMatrix();
glPushMatrix(); // teeth
glTranslated(0.045, 0.255, 0.34);
glRotated(-90, 1, 0, 0);
glutSolidCone(0.01, 0.02, 16, 16);
glPopMatrix();
glColor3d(0.5, 0.85, 0.88); // body
glTranslatef(0, 0, 0.1);
glPushMatrix();
glRotated((GLfloat)body, 1, 0, 0);
glutSolidSphere(0.3, 40, 50);
glPopMatrix();
glPushMatrix();
glTranslatef(0, 0.7, 0.0);
glRotatef((GLfloat)stage, 0.0, 1.0, 0.0);
glTranslatef(1.0, 0.0, 0.0);
glPushMatrix();
glScalef(2.0, 0.4, 1.0);
glutWireCube(1.0);
glPopMatrix();
//glFlush();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glBindTexture(GL_TEXTURE_2D, myTexture);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
/*glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); */
glNormal3f(0.0, 1.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-2.5f, -2.5f, 2.5f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(2.5f, -2.5f, 2.5f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(2.5f, -2.5f, -2.5f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-2.5f, -2.5f, -2.5f);
glEnd();
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
glutSwapBuffers();
}
void reshape(int width, int height)
{
if (height == 0) height = 1; // To prevent divide by 0
GLfloat aspect = (GLfloat)width / (GLfloat)height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//glFrustum(-ar + 1, ar - 1, -1.0, 1.0, 2.0, 90.0);
//gluOrtho2D(0, width, 0, height);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(640, 480);
glutCreateWindow("SOIL test");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
myTexture = SOIL_load_OGL_texture("background.png", 0, 1, SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_INVERT_Y);
if (!myTexture)
{
printf("soil failed to load texture\n");
}
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHT0);
glEnable(GL_NORMALIZE);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_LIGHTING);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glutMainLoop();
return EXIT_SUCCESS;
}
If you want that the background image is draw in the back, then you've to draw the background first, but disable the Depth Test (The depth buffer has to be cleared before).
This causes that the other geometry covers the background.
When the background is drawn no projection matrix is set, the projection matrix is the identity matrix. So the z-coordinate of the background has to be in [-1, 1], else it wold be clipped by the near or far plane.
If texturing is enabled, then by default the color of the texel is multiplied by the current color, because by default the texture environment mode (GL_TEXTURE_ENV_MODE) is GL_MODULATE. See glTexEnv.
This causes that the color of the texels of the texture is "mixed" by the last color which you have set by glColor3d.
Set a "white" color before you render the texture:
glColor3d(1.0, 1.0, 1.0);
Note, OpenGL is a state engine. If a color was set, the color is kept until it is changed again, even beyond frames. So this might not be an issue in the first frame, but it would be in the further frames.
The fixed function light model is applied on the background, too. This will cause a bad look with fixed function gouraud light model. I recommend to disable lighting before you draw the background.
glDisable(GL_LIGHTING);
and to enable lighting before you draw the geometry
glEnable(GL_LIGHTING);
The function display may look like this:
void display(void)
{
// clear color buffer and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// prepare for drawing the back ground
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glColor3d(1.0, 1.0, 1.0);
// projection and model view for the background
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// draw the background
glBindTexture(GL_TEXTURE_2D, myTexture);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glEnd();
// prepare for drawing the geometry
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
// projection and model view for the geoemtry
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//glFrustum(-ar + 1, ar - 1, -1.0, 1.0, 2.0, 90.0);
//gluOrtho2D(0, width, 0, height);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// draw geometry
glColor3d(0.5, 0.85, 0.9); // head
// ...
glFlush();
glutSwapBuffers();
glutPostRedisplay();
}
I have a pixmap for some app in Xephyr and I need draw this pixmap on rectangle openGL. I seen example from khronos for pixmap when created in code but it's not working for me:
mPixmap = XCreatePixmap(dpy, client->getWindow(), static_cast<unsigned int>(attr.width),
static_cast<unsigned int>(attr.height), static_cast<unsigned int>(attr.depth));
And code where I drawed:
void startPluginPixmap() {
XEvent xev;
GLuint texture_id;
GLint pix_att[5] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None };
vi = glXChooseVisual(dpy, 0, pix_att);
swa.event_mask = ExposureMask | KeyPressMask;
swa.colormap = XCreateColormap(dpy, root, vi->visual, AllocNone);
uint64_t window_width = 300;
uint64_t window_height = 400;
uint32_t window_depth = vi->depth;
win = XCreateWindow(dpy, root, 0, 0, window_width, window_height, 0, window_depth, InputOutput, vi->visual, CWEventMask | CWColormap, &swa);
XMapWindow(dpy, win);
XStoreName(dpy, win, "PIXMAP TEST");
glc = glXCreateContext(dpy, vi, NULL, GL_TRUE);
if (!glc) {
exit(0);
}
glXMakeCurrent(dpy, win, glc);
glEnable(GL_DEPTH_TEST);
uint64_t pixmap_width = 150;
uint64_t pixmap_height = 100;
GC gc = DefaultGC(dpy, 0);
XFlush(dpy);
XImage * xim = XGetImage(dpy, mPixmap, 0, 0, pixmap_width, pixmap_height, AllPlanes, ZPixmap);
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &texture_id);
glBindTexture(GL_TEXTURE_2D, texture_id);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, pixmap_width, pixmap_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (void *)(&(xim->data[0])));
XDestroyImage(xim);
while(true) {
XNextEvent(dpy, &xev);
if (xev.type == Expose) {
redrawPixmapImage();
}
else if (xev.type == KeyPress && xev.xkeymap.type == 0x19) {
glXMakeCurrent(dpy, None, NULL);
glXDestroyContext(dpy, glc);
XDestroyWindow(dpy, win);
XCloseDisplay(dpy);
exit(0);
}
}
}
void Cube::redrawPixmapImage() {
XWindowAttributes gwa;
XGetWindowAttributes(dpy, win, &gwa);
glViewport(0, 0, gwa.width, gwa.height);
glClearColor(.0, 1.0, .0, .5);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.25, 1.25, -1.25, 1.25, 1., 20.);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0., 0., 10., 0., 0., 0., 0., 1., 0.);
glColor3f(1.f, 1.f, 1.f);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0);
//glColor3f(1.f, 0.f, 0.f);
glVertex3f(-1.0, 1.0, 0.0);
glTexCoord2f(1.0, 0.0);
glVertex3f( 1.0, 1.0, 0.0);
glTexCoord2f(1.0, 1.0);
glVertex3f( 1.0, -1.0, 0.0);
glTexCoord2f(0.0, 1.0);
glVertex3f(-1.0, -1.0, 0.0);
glTexCoord2f(1.0, 1.0);
glVertex3f(-1.0, 1.0, 0.0);
glEnd();
glXSwapBuffers(dpy, win);
}
In this code I enter width and height manual because get it in debug info.
And for me this calculation of textcoord doesn't work (When I run in Xephyr xeyes, and then this code, I seeing artifacts and green area).
So, how I can calculate texcoords for pixmap some app?
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'm trying to learn how to use textures in OpenGL.I don't have freeimage installed so I had to create the bitmap with a for loop.
What I'm trying to do is to simply take a texture with all red points, and to map it inside a square:
#import <OpenGL/OpenGL.h>
#import <GLUT/GLUT.h>
#import <stdlib.h>
#import <string.h>
#import <math.h>
GLuint texture;
GLfloat (*pixels) [3];
void init()
{
// Inizializzazione
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, 1, 1, 1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, -100, 0, 0, 0, 0, 1, 0);
// Inizializzazione della texture
glGenTextures(1, &texture);
pixels= malloc(256*256*sizeof(GLfloat[3]));
for(GLuint i=0; i<256*256;i++)
{
pixels[i][0]=1.0;
pixels[i][1]= pixels[i][2]= 0.0;
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB, GL_FLOAT, pixels);
}
void display()
{
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
glPushMatrix();
glBegin(GL_QUADS);
glVertex3f(0, 0, 0);
glTexCoord2f(0.0, 0.0);
glVertex3f(10, 0, 0);
glTexCoord2f(0.0, 1.0);
glVertex3f(10, 10, 0);
glTexCoord2f(1.0, 1.0);
glVertex3f(0, 10, 0);
glTexCoord2f(0.0, 1.0);
glEnd();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glutSwapBuffers();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowPosition(100, 100);
glutInitWindowSize(600, 600);
glutCreateWindow(argv[0]);
glutDisplayFunc(display);
init();
glutMainLoop();
free(pixels);
return 0;
}
The problem is that all the pixels are red, but I get a white square instead of a red one:
You need to bind the texture before you upload data to it, so use glBindTexture before glTexImage2D. Also as it stands the texture will be incomplete, since it has no mipmaps and the default values for minification and magnification filters require them. Use glTexParameter to set the filters to linear, or otherwise create mipmaps.
Give this a shot:
#include <GL/glut.h>
GLuint texture;
void init()
{
// Inizializzazione della texture
unsigned int i;
GLfloat* pixels = (GLfloat*)malloc( 256 * 256 * sizeof( GLfloat ) * 3 );
for( i = 0; i < 256 * 256; i++ )
{
GLuint base = i * 3;
pixels[ base + 0 ] = 1.0f;
pixels[ base + 1 ] = 0.0f;
pixels[ base + 2 ] = 0.0f;
}
glGenTextures(1, &texture);
glBindTexture( GL_TEXTURE_2D, texture );
// disable mipmap filtering since we aren't uploading mipmaps
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB, GL_FLOAT, pixels );
free( pixels);
}
void display( void )
{
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, 1, 1, 1000);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, -100, 0, 0, 0, 0, 1, 0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
// important because GL_TEXTURE_ENV defaults to GL_MODULATE
glColor3ub(255,255,255);
glPushMatrix();
glBegin(GL_QUADS);
glVertex3f(0, 0, 0);
glTexCoord2f(0.0, 0.0);
glVertex3f(10, 0, 0);
glTexCoord2f(0.0, 1.0);
glVertex3f(10, 10, 0);
glTexCoord2f(1.0, 1.0);
glVertex3f(0, 10, 0);
glTexCoord2f(0.0, 1.0);
glEnd();
glPopMatrix();
glDisable(GL_TEXTURE_2D);
glutSwapBuffers();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowPosition(100, 100);
glutInitWindowSize(600, 600);
glutCreateWindow(argv[0]);
init();
glutDisplayFunc(display);
glutMainLoop();
return 0;
}