I'm just trying to draw a bunch of lines that make up a "cube". I can't for the life of me figure out why this is producing a black screen. The debugger does not break at any point.
I'm sure it's a problem with my pointers, as I'm only decent at them in regular c++ and in OpenGL it gets even worse.
const char* vertexSource =
"#version 150\n"
"in vec3 position;"
"void main() {"
" gl_Position = vec4(position, 1.0);"
"}";
const char* fragmentSource =
"#version 150\n"
"out vec4 outColor;"
"void main() {"
" outColor = vec4(1.0, 1.0, 1.0, 1.0);"
"}";
int main() {
initializeGLFW();
// Initialize GLEW
glewExperimental = GL_TRUE;
glewInit();
// Create Vertex Array Object
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Create a Vertex Buffer Object and copy the vertex data to it
GLuint vbo;
glGenBuffers( 1, &vbo );
float vertices[] = {
1.0f, 1.0f, 1.0f, // Vertex 0 (X, Y, Z)
-1.0f, 1.0f, 1.0f, // Vertex 1 (X, Y, Z)
-1.0f, -1.0f, 1.0f, // Vertex 2 (X, Y, Z)
1.0f, -1.0f, 1.0f, // Vertex 3 (X, Y, Z)
1.0f, 1.0f, -1.0f, // Vertex 4 (X, Y, Z)
-1.0f, 1.0f, -1.0f, // Vertex 5 (X, Y, Z)
-1.0f, -1.0f, -1.0f, // Vertex 6 (X, Y, Z)
1.0f, -1.0f, -1.0f // Vertex 7 (X, Y, Z)
};
GLuint indices[] = {
0, 1,
1, 2,
2, 3,
3, 0,
4, 5,
5, 6,
6, 7,
7, 4,
0, 4,
1, 5,
2, 6,
3, 7
};
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, sizeof( vertices ), vertices, GL_STATIC_DRAW );
//glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vbo);
//glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( indices ), indices, GL_STATIC_DRAW );
// Create and compile the vertex shader
GLuint vertexShader = glCreateShader( GL_VERTEX_SHADER );
glShaderSource( vertexShader, 1, &vertexSource, NULL );
glCompileShader( vertexShader );
// Create and compile the fragment shader
GLuint fragmentShader = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( fragmentShader, 1, &fragmentSource, NULL );
glCompileShader( fragmentShader );
// Link the vertex and fragment shader into a shader program
GLuint shaderProgram = glCreateProgram();
glAttachShader( shaderProgram, vertexShader );
glAttachShader( shaderProgram, fragmentShader );
glBindFragDataLocation( shaderProgram, 0, "outColor" );
glLinkProgram (shaderProgram);
glUseProgram( shaderProgram);
// Specify the layout of the vertex data
GLint posAttrib = glGetAttribLocation( shaderProgram, "position" );
glEnableVertexAttribArray( posAttrib );
glVertexAttribPointer( posAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0 );
// Main loop
while(glfwGetWindowParam(GLFW_OPENED)) {
// Clear the screen to black
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT );
// Draw lines from 2 vertices
glDrawElements(GL_LINES, sizeof(indices), GL_UNSIGNED_INT, indices );
// Swap buffers
glfwSwapBuffers();
}
// Clean up
glDeleteProgram( shaderProgram );
glDeleteShader( fragmentShader );
glDeleteShader( vertexShader );
//glDeleteBuffers( 1, &ebo );
glDeleteBuffers( 1, &vbo );
glDeleteVertexArrays( 1, &vao );
glfwTerminate();
exit( EXIT_SUCCESS );
}
EDIT: Full code trying the first answer's recommendation. Still blank.
#define GLEW_STATIC
#include <GL/glew.h>
#include <GL/glfw.h>
#include <iostream>
#pragma comment( lib, "glfw.lib")
#pragma comment( lib, "opengl32.lib")
#pragma comment( lib, "glew32s.lib")
const char* vertexSource =
"#version 150\n"
"in vec3 position;"
"void main() {"
" gl_Position = vec4(position.x, position.y, position.z - 0.9, 1.0);"
"}";
const char* fragmentSource =
"#version 150\n"
"out vec4 outColor;"
"void main() {"
" outColor = vec4(1.0, 1.0, 1.0, 1.0);"
"}";
void initializeGLFW();
int main() {
initializeGLFW();
// Initialize GLEW
glewExperimental = GL_TRUE;
glewInit();
// Create Vertex Array Object
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Create a Vertex Buffer Object and copy the vertex data to it
GLuint vbo;
glGenBuffers( 1, &vbo );
float vertices[] = {
1.0f, 1.0f, 1.0f, // Vertex 0 (X, Y, Z)
-1.0f, 1.0f, 1.0f, // Vertex 1 (X, Y, Z)
-1.0f, -1.0f, 1.0f, // Vertex 2 (X, Y, Z)
1.0f, -1.0f, 1.0f, // Vertex 3 (X, Y, Z)
1.0f, 1.0f, -1.0f, // Vertex 4 (X, Y, Z)
-1.0f, 1.0f, -1.0f, // Vertex 5 (X, Y, Z)
-1.0f, -1.0f, -1.0f, // Vertex 6 (X, Y, Z)
1.0f, -1.0f, -1.0f // Vertex 7 (X, Y, Z)
};
size_t vertCount = sizeof( vertices ) / sizeof( float );
for( size_t i = 0; i < vertCount; ++i ) {
vertices[i] /= 2.0f;
}
GLubyte indices[] = {
0, 1,
1, 2,
2, 3,
3, 0,
4, 5,
5, 6,
6, 7,
7, 4,
0, 4,
1, 5,
2, 6,
3, 7
};
glBindBuffer( GL_ARRAY_BUFFER, vbo );
//glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, vbo);
glBufferData( GL_ARRAY_BUFFER, sizeof( vertices ), vertices, GL_STATIC_DRAW );
// Create and compile the vertex shader
GLuint vertexShader = glCreateShader( GL_VERTEX_SHADER );
glShaderSource( vertexShader, 1, &vertexSource, NULL );
glCompileShader( vertexShader );
// Create and compile the fragment shader
GLuint fragmentShader = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( fragmentShader, 1, &fragmentSource, NULL );
glCompileShader( fragmentShader );
// Link the vertex and fragment shader into a shader program
GLuint shaderProgram = glCreateProgram();
glAttachShader( shaderProgram, vertexShader );
glAttachShader( shaderProgram, fragmentShader );
glBindFragDataLocation( shaderProgram, 0, "outColor" );
glLinkProgram (shaderProgram);
glUseProgram( shaderProgram);
// Specify the layout of the vertex data
GLint posAttrib = glGetAttribLocation( shaderProgram, "position" );
glEnableVertexAttribArray( posAttrib );
glVertexAttribPointer( posAttrib, 3, GL_FLOAT, GL_FALSE, 0, vertices );
// Main loop
while(glfwGetWindowParam(GLFW_OPENED)) {
// Clear the screen to black
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT );
// Draw lines from 2 vertices
glDrawElements(GL_LINES, 24, GL_UNSIGNED_BYTE, indices);
// Swap buffers
glfwSwapBuffers();
}
// Clean up
glDeleteProgram( shaderProgram );
glDeleteShader( fragmentShader );
glDeleteShader( vertexShader );
//glDeleteBuffers( 1, &ebo );
glDeleteBuffers( 1, &vbo );
glDeleteVertexArrays( 1, &vao );
glfwTerminate();
exit( EXIT_SUCCESS );
}
void initializeGLFW() {
glfwInit();
glfwOpenWindowHint( GLFW_OPENGL_VERSION_MAJOR, 3 );
glfwOpenWindowHint( GLFW_OPENGL_VERSION_MINOR, 2 );
glfwOpenWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
glfwOpenWindowHint( GLFW_WINDOW_NO_RESIZE, GL_TRUE );
glfwOpenWindow( 800, 600, 0, 0, 0, 0, 0, 0, GLFW_WINDOW );
glfwSetWindowTitle( "OpenGL" );
}
The "default" projection is essentially glOrtho(-1, 1, -1, 1, -1, 1) with the camera at (0,0,0) looking down the -Z axis.
Move the camera back:
const char* vertexSource =
"#version 150\n"
"in vec3 position;"
"void main() {"
" gl_Position = vec4(position.x, position.y, position.z - 0.9, 1.0);"
"}";
And make your object smaller:
float vertices[] = {
1.0f, 1.0f, 1.0f, // Vertex 0 (X, Y, Z)
-1.0f, 1.0f, 1.0f, // Vertex 1 (X, Y, Z)
-1.0f, -1.0f, 1.0f, // Vertex 2 (X, Y, Z)
1.0f, -1.0f, 1.0f, // Vertex 3 (X, Y, Z)
1.0f, 1.0f, -1.0f, // Vertex 4 (X, Y, Z)
-1.0f, 1.0f, -1.0f, // Vertex 5 (X, Y, Z)
-1.0f, -1.0f, -1.0f, // Vertex 6 (X, Y, Z)
1.0f, -1.0f, -1.0f // Vertex 7 (X, Y, Z)
};
size_t vertCount = sizeof( vertices ) / sizeof( float );
for( size_t i = 0; i < vertCount; ++i )
{
vertices[i] /= 2.0f;
}
Complete:
#include <GL/glew.h>
#include <GL/glfw.h>
#include <cstdlib>
const char* vertexSource =
"#version 150\n"
"in vec3 position;"
"void main() {"
" gl_Position = vec4(position.x, position.y, position.z - 0.9, 1.0);"
"}";
const char* fragmentSource =
"#version 150\n"
"out vec4 outColor;"
"void main() {"
" outColor = vec4(1.0, 1.0, 1.0, 1.0);"
"}";
void initializeGLFW()
{
glfwInit();
glfwOpenWindowHint( GLFW_OPENGL_VERSION_MAJOR, 3 );
glfwOpenWindowHint( GLFW_OPENGL_VERSION_MINOR, 2 );
glfwOpenWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
glfwOpenWindowHint( GLFW_WINDOW_NO_RESIZE, GL_TRUE );
glfwOpenWindow( 800, 600, 0, 0, 0, 0, 0, 0, GLFW_WINDOW );
glfwSetWindowTitle( "OpenGL" );
}
int main()
{
initializeGLFW();
// Initialize GLEW
glewExperimental = GL_TRUE;
glewInit();
// Create Vertex Array Object
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Create a Vertex Buffer Object and copy the vertex data to it
GLuint vbo;
glGenBuffers( 1, &vbo );
float vertices[] =
{
1.0f, 1.0f, 1.0f, // Vertex 0 (X, Y, Z)
-1.0f, 1.0f, 1.0f, // Vertex 1 (X, Y, Z)
-1.0f, -1.0f, 1.0f, // Vertex 2 (X, Y, Z)
1.0f, -1.0f, 1.0f, // Vertex 3 (X, Y, Z)
1.0f, 1.0f, -1.0f, // Vertex 4 (X, Y, Z)
-1.0f, 1.0f, -1.0f, // Vertex 5 (X, Y, Z)
-1.0f, -1.0f, -1.0f, // Vertex 6 (X, Y, Z)
1.0f, -1.0f, -1.0f // Vertex 7 (X, Y, Z)
};
size_t vertCount = sizeof( vertices ) / sizeof( float );
for( size_t i = 0; i < vertCount; ++i )
{
vertices[i] /= 2.0f;
}
GLuint indices[] =
{
0, 1,
1, 2,
2, 3,
3, 0,
4, 5,
5, 6,
6, 7,
7, 4,
0, 4,
1, 5,
2, 6,
3, 7
};
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, sizeof( vertices ), vertices, GL_STATIC_DRAW );
// Create and compile the vertex shader
GLuint vertexShader = glCreateShader( GL_VERTEX_SHADER );
glShaderSource( vertexShader, 1, &vertexSource, NULL );
glCompileShader( vertexShader );
// Create and compile the fragment shader
GLuint fragmentShader = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( fragmentShader, 1, &fragmentSource, NULL );
glCompileShader( fragmentShader );
// Link the vertex and fragment shader into a shader program
GLuint shaderProgram = glCreateProgram();
glAttachShader( shaderProgram, vertexShader );
glAttachShader( shaderProgram, fragmentShader );
glBindFragDataLocation( shaderProgram, 0, "outColor" );
glLinkProgram (shaderProgram);
glUseProgram( shaderProgram);
// Specify the layout of the vertex data
GLint posAttrib = glGetAttribLocation( shaderProgram, "position" );
glEnableVertexAttribArray( posAttrib );
glVertexAttribPointer( posAttrib, 3, GL_FLOAT, GL_FALSE, 0, 0 );
// Main loop
while(glfwGetWindowParam(GLFW_OPENED))
{
// Clear the screen to black
glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
glClear( GL_COLOR_BUFFER_BIT );
// Draw lines from 2 vertices
glDrawElements(GL_LINES, sizeof(indices), GL_UNSIGNED_INT, indices );
// Swap buffers
glfwSwapBuffers();
}
// Clean up
glDeleteProgram( shaderProgram );
glDeleteShader( fragmentShader );
glDeleteShader( vertexShader );
//glDeleteBuffers( 1, &ebo );
glDeleteBuffers( 1, &vbo );
glDeleteVertexArrays( 1, &vao );
glfwTerminate();
exit( EXIT_SUCCESS );
}
Related
I'm using OpenGL 3.3 on Mac OSX 11.5.2. I have 6 fragment shaders, 3 that works and 3 that crashes with EXC_BAD_ACCESS. They all use the same vertex shader. There have been many questions about this problem, but I've made sure to:
Unbind my previous state.
Made sure attribute arrays enabled and used.
Am only using a single-thread, i.e. no concurrency.
The shaders that crash are all using one array of offsets and a kernel to do post-processing effects. If I replace texture_coordinate.st + offsets[i] with just texture_coordinate.st, it'll work just fine. As this makes the offsets array unused and optimized out, I have a suspicion that it could be due to a register allocation bug as mentioned in the comments in this question, but can't confirm.
I've also checked for other problems, such as loading them in different orders, using different compiler flags, but the crashes are consistent.
Here's a minimal, reproducible example (dependent on glad and glfw3, compiled with c++17) with one of the problematic shaders.
#include <glad/glad.h>
#include <GLFW/glfw3.h>
const char VERTEX_POST[] = R"(
#version 330 core
layout (location = 0) in vec2 position;
layout (location = 1) in vec2 in_texture_coordinate;
out vec2 texture_coordinate;
void main()
{
gl_Position = vec4(position.x, position.y, 0.0, 1.0);
texture_coordinate = in_texture_coordinate;
}
)";
const char FRAGMENT_POST[] = R"(
#version 330 core
in vec2 texture_coordinate;
out vec4 FragColor;
uniform sampler2D image;
const float offset = 1.0 / 300.0;
void main()
{
vec2 offsets[9] = vec2[](
vec2(-offset, offset), // top-left
vec2( 0.0f, offset), // top-center
vec2( offset, offset), // top-right
vec2(-offset, 0.0f), // center-left
vec2( 0.0f, 0.0f), // center-center
vec2( offset, 0.0f), // center-right
vec2(-offset, -offset), // bottom-left
vec2( 0.0f, -offset), // bottom-center
vec2( offset, -offset) // bottom-right
);
float kernel[9] = float[](
-1, -1, -1,
-1, 9, -1,
-1, -1, -1
);
vec3 sample_texture[9];
for(int i = 0; i < 9; i++)
sample_texture[i] = vec3(texture(image, texture_coordinate + offsets[i]));
vec3 color = vec3(0.0);
for (int i = 0; i < 9; i++)
color += sample_texture[i] * kernel[i];
FragColor = vec4(color, 1.0);
}
)";
float vertices[] = {
// Positions // Texture coords
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f, 1.0f, 1.0f
};
GLuint create_shader(const char* source, GLenum type)
{
GLuint id = glCreateShader(type);
glShaderSource(id, 1, &source, nullptr);
glCompileShader(id);
int success;
glGetShaderiv(id, GL_COMPILE_STATUS, &success);
assert(success);
return id;
}
int main()
{
// ---- INIT GLFW & GLAD ----
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);
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
GLFWwindow* window = glfwCreateWindow(800, 800, "Temp", nullptr, nullptr);
if (window == nullptr) return -1;
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) return -1;
// ---- CREATE QUAD ----
GLuint quad, vbo;
glGenVertexArrays(1, &quad);
glGenBuffers(1, &vbo);
glBindVertexArray(quad);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(3 * sizeof(float)));
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// ---- CREATE TEXTURE ----
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
char data[800 * 800 * 4] = {};
for (char& i : data) i = 127;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 800, 800, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
// ---- CREATE SHADER PROGRAM ----
GLuint vertex_shader = create_shader(VERTEX_POST, GL_VERTEX_SHADER);
GLuint fragment_shader = create_shader(FRAGMENT_POST, GL_FRAGMENT_SHADER);
GLuint program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
glValidateProgram(program);
int success;
glGetProgramiv(program, GL_LINK_STATUS, &success);
assert(success);
// ---- MAIN LOOP ----
while (!glfwWindowShouldClose(window))
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(glGetUniformLocation(program, "image"), 0);
glBindVertexArray(quad);
glDrawArrays(GL_TRIANGLES, 0, 6);
glfwSwapBuffers(window);
glfwPollEvents();
}
return 0;
}
The example gives me a grey image when not including offsets and otherwise exhibits the crash. What could be causing this?
I have no errors but when I run the program all I have is a black screen and I am supposed to have two triangles:
#include <iostream> //includes C++ i/o stream
#include <GL/glew.h> //includes glew header
#include <GL/freeglut.h> //includes freeglut header
using namespace std; //Uses the standard namespace
#define WINDOW_TITLE "3-1 Assignment" //Macro for window title
//Vertex and Fragment shader source macro
#ifndef GLSL
#define GLSL(Version, Source) "#version " #Version "\n" #Source
#endif
//Windows Variables for height and width
int WindowWidth=800, WindowHeight=600;
/*User-defined function prototypes to: initialize the program, set the window size, redraw graphics on the window when resized and render graphics on the screen*/
void UInitalize(int, char*[]);
void UInitWindow(int, char*[]);
void UResizeWindow(int, int);
void URenderGraphics(void);
void UCreateShaders(void);
void UCreateVBO();
//Vertex and Shader program source code
const GLchar * VertexShader = GLSL(440,
//Receive Vertex coordinates from attribute
in layout(location=0) vec4 vertex_Position;
//for attribute 1 expect vec(4) floats passed into the vertex shader
in layout(location=1) vec4 colorFromVBO;
//Declare a vec4 variable that will reference the vertex colors passed into the vertex shader from the buffer
out vec4 colorFromVShader;
void main(){
//Sends vertex positions
gl_Position= vertex_Position;
//References vertex colors sent from the buffer
colorFromVShader= colorFromVBO;
}
);
const GLchar * FragmentShader = GLSL(440,
//vertex colors from the shader
in vec4 colorFromVShader;
//vec 4 variable that will reference vertex colors passed into the fragment shader from the vertex shader
out vec4 vertex_color;
void main(){
//gl_FragCOlor= vec4(0.0, 1.0, 0.0, 1.0);
vertex_Color= colorFromVShader;
}
);
//Main Function
int main(int argc, char* argv[])
{
UInitalize(argc, argv); //Initialize openGL program
glutMainLoop(); //Starts openGL loop in background
exit(EXIT_SUCCESS); //Ends the program
}
//Implements createVBO function
void UCreateVBO(void)
{
// Specifies Coordinates
GLfloat verts[]=
{
/*index 0*/
-1.0f, 1.0f, // top-center of the screen
1.0f, 0.0f, 0.0f, 1.0f, // Red vertex
/*index 1*/
-1.0f, 0.0f, // bottom-left of the screen
0.0f, 0.0f, 1.0f, 1.0f, // Blue vertex
/*index 2*/
-0.5f, 0.0f, // bottom-right of the screen
0.0f, 1.0f, 0.0f, 1.0f, // Green vertex
/*index 3*/
0.0f, 0.0f, // bottom-left of the screen
1.0f, 0.0f, 0.0f, 1.0f, // Red vertex
/*index 4*/
0.0f, -1.0f, // bottom-right of the screen
0.0f, 1.0f, 0.0f, 1.0f, // Green vertex
};
//Stores the size of the verts array
float numVertices= sizeof(verts);
//Variable for the vertex buffer object id
GLuint myBufferID;
//creates 1 buffer
glGenBuffers(1, &myBufferID);
//Activates the buffer
glBindBuffer(GL_ARRAY_BUFFER, myBufferID);
//Sends vertex data to the GPU
glBufferData(GL_ARRAY_BUFFER, numVertices, verts, GL_STATIC_DRAW);
//Creates vertex attribute pointer
//Number of coordinates per vertex
GLuint floatsPerVertex= 2;
//Specifies the initial position of the coordinates in the buffer
glEnableVertexAttribArray(0);
//Strides between vertex coordinates is 6 (x, y ,r, g, b, a)
//the number of floats before each vertex position
GLint vertexStride= sizeof(float)*6;
//Instructs GPU on how to handle the vertex buffer object
//parameters: atrribPointerPosition | coordinates per vertex|data type| deactivate normalizations | 0 strides | 0 offset
glVertexAttribPointer(0, floatsPerVertex, GL_FLOAT, GL_FALSE, vertexStride, 0);
//Sets an attribute pointer for the vertex colors
glEnableVertexAttribArray(1);
GLint colorStride= sizeof(float)*6;
//Parameters: attribPointerPosition 1 | floats per color is 4 | data type | deactivate normalization | 6 strides until the next color | 2 floats until the beginning of each color
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, colorStride, (char*)(sizeof(float)*2));
//Creates a buffer object for the indexes
GLushort indicies[]= {0,1,2,2,3,4};
float numIndicies= sizeof(indicies);
GLuint indexBufferID;
glGenBuffers(1, &indexBufferID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndicies, indicies, GL_STATIC_DRAW);
}
//Implements UInitalize function
void UInitalize(int argc, char* argv[])
{
//glew status variable
GLenum GlewInitResult;
UInitWindow(argc, argv);
//Check glew status
GlewInitResult= glewInit();
if (GLEW_OK != GlewInitResult)
{
fprintf(stderr,"ERROR: %s\n", glewGetErrorString(GlewInitResult));
exit(EXIT_FAILURE);
}
//Display GPU OpenGl version
fprintf(stdout, "INFO: OpenGL Version: %s\n", glGetString(GL_VERSION));
//Makes the screen black
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}
//Implements the UInitWindow function
void UInitWindow(int argc, char* argv[])
{
//Initialize freeglut
glutInit(&argc, argv);
//Set window size
glutInitWindowSize(WindowWidth, WindowHeight);
//Memory buffer setup for display
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
//Creates a window with the macro placeholder title
glutCreateWindow(WINDOW_TITLE);
//Called when window is resized
glutReshapeFunc(UResizeWindow);
//Renders graphics on the screen
glutDisplayFunc(URenderGraphics);
}
//Implements the UResizeWindow function
void UResizeWindow(int Width, int Height)
{
glViewport(0, 0, Width, Height);
}
//Implements the URenderGraphics
void URenderGraphics(void)
{
//Clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//Create the triangle
//Specifies the number of vertexes
GLuint totalVertices = 6;
//Draw the triangles
//glDrawArrays(GL_TRIANGLES, 0, totalVertices);
glDrawElements(GL_TRIANGLES, totalVertices, GL_UNSIGNED_SHORT, NULL);
//Flips the back buffer with the front buffer every frame, akin to GL Flush
glutSwapBuffers();
}
//Initialize the UCreateShaders function
void UCreateShaders(void)
{
//Create a shader program object
GLuint ProgramId = glCreateProgram();
//Create the vertex shader
GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER);
//Create the fragment shader
GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER);
//Get the source for the vertex shader
glShaderSource(vertexShaderId, 1, &VertexShader, NULL);
//Get the source for the fragment shader
glShaderSource(fragmentShaderId, 1, &FragmentShader, NULL);
//Complies the vertex shader
glCompileShader(vertexShaderId);
//Compiles the fragment shader
glCompileShader(fragmentShaderId);
//Attach shaders
glAttachShader(ProgramId, vertexShaderId);
glAttachShader(ProgramId, fragmentShaderId);
//Link the shader program
glLinkProgram(ProgramId);
//Utilizes the shader program
glUseProgram(ProgramId);
}
Couple issues:
UCreateShaders() and UCreateVBO() are never called.
Without a shader or geometry bound glDrawElements() can't do anything useful.
Fragment shader case mismatch causing a link failure: vertex_color != vertex_Color:
0:6(2): error: `vertex_Color' undeclared
0:6(2): error: value of type vec4 cannot be assigned to variable of type error
Make sure to check GL_COMPILE_STATUS & GL_LINK_STATUS & grab the appropriate info logs (glGetShaderInfoLog()/glGetProgramInfoLog()) when loading shaders to help identify issues like this in the future.
All together:
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <cstdio>
#include <cstdlib>
#include <iostream>
void CheckStatus( GLuint obj, bool isShader )
{
GLint status = GL_FALSE, log[ 1 << 11 ] = { 0 };
( isShader ? glGetShaderiv : glGetProgramiv )( obj, isShader ? GL_COMPILE_STATUS : GL_LINK_STATUS, &status );
if( status == GL_TRUE ) return;
( isShader ? glGetShaderInfoLog : glGetProgramInfoLog )( obj, sizeof( log ), NULL, (GLchar*)log );
std::cerr << (GLchar*)log << "\n";
std::exit( EXIT_FAILURE );
}
void AttachShader( GLuint program, GLenum type, const char* src )
{
GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader, true );
glAttachShader( program, shader );
glDeleteShader( shader );
}
const char* const vert = R"GLSL(
#version 440
in layout(location=0) vec4 vertex_Position;
in layout(location=1) vec4 colorFromVBO;
out vec4 colorFromVShader;
void main()
{
gl_Position = vertex_Position;
colorFromVShader = colorFromVBO;
}
)GLSL";
const char* const frag = R"GLSL(
#version 440
in vec4 colorFromVShader;
out vec4 vertex_color;
void main()
{
vertex_color = colorFromVShader;
}
)GLSL";
void UCreateShaders()
{
GLuint prog = glCreateProgram();
AttachShader( prog, GL_VERTEX_SHADER, vert );
AttachShader( prog, GL_FRAGMENT_SHADER, frag );
glLinkProgram( prog );
CheckStatus( prog, false );
glUseProgram( prog );
}
void UCreateVBO()
{
// Specifies Coordinates
GLfloat verts[]=
{
/*index 0*/
-1.0f, 1.0f, // top-center of the screen
1.0f, 0.0f, 0.0f, 1.0f, // Red vertex
/*index 1*/
-1.0f, 0.0f, // bottom-left of the screen
0.0f, 0.0f, 1.0f, 1.0f, // Blue vertex
/*index 2*/
-0.5f, 0.0f, // bottom-right of the screen
0.0f, 1.0f, 0.0f, 1.0f, // Green vertex
/*index 3*/
0.0f, 0.0f, // bottom-left of the screen
1.0f, 0.0f, 0.0f, 1.0f, // Red vertex
/*index 4*/
0.0f, -1.0f, // bottom-right of the screen
0.0f, 1.0f, 0.0f, 1.0f, // Green vertex
};
//Variable for the vertex buffer object id
GLuint myBufferID;
glGenBuffers(1, &myBufferID);
glBindBuffer(GL_ARRAY_BUFFER, myBufferID);
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float)*6, 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(float)*6, (char*)(sizeof(float)*2));
glEnableVertexAttribArray(1);
//Creates a buffer object for the indexes
GLushort indicies[]= {0,1,2,2,3,4};
GLuint indexBufferID;
glGenBuffers(1, &indexBufferID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indicies), indicies, GL_STATIC_DRAW);
}
void URenderGraphics(void)
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLuint totalVertices = 6;
glDrawElements(GL_TRIANGLES, totalVertices, GL_UNSIGNED_SHORT, NULL);
glutSwapBuffers();
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitWindowSize(640, 480);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutCreateWindow("GLUT");
glutDisplayFunc(URenderGraphics);
GLenum GlewInitResult = glewInit();
if (GLEW_OK != GlewInitResult)
{
fprintf(stderr,"ERROR: %s\n", glewGetErrorString(GlewInitResult));
exit(EXIT_FAILURE);
}
fprintf(stdout, "INFO: OpenGL Version: %s\n", glGetString(GL_VERSION));
UCreateVBO();
UCreateShaders();
glutMainLoop();
return 0;
}
I'm trying to learn displaying Texture using Shader program using OpenGL 3.30. I'm able to load the image but I can't get it displayed correctly on each cube's face.
The code below defines properties of a Vertex, which is its vertices and texture coordinates associated with each cube's vertex. Then 2 VBOs are created, one holds cube vertices and the other one holds textures information.
I think I'm very closed to the final result: I got the cube, loaded image successfully, able to get image information. So what did I do wrongly here?
I'm using stblib to load the image.
This is my code:
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stddef.h> /* must include for the offsetof macro */
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <stdlib.h>
#include "utils.h"
#include "stb_image.h"
struct Vertex {
GLdouble position[3];
GLdouble texture[2];
};
/* These pointers will receive the contents of our shader source code files */
GLchar *vertexsource, *fragmentsource;
/* These are handles used to reference the shaders */
GLuint vertexshader, fragmentshader;
/* This is a handle to the shader program */
GLuint shaderprogram;
GLuint vbo[1]; /* Create handles for our Vertex Array Object and One Vertex Buffer Object */
//GLuint text_2d_1;
const struct Vertex plane[24] = {
// Front Face
{{1.0f, 1.0f, 1.0f}, {0.0, 0.0}},
{{-1.0f, 1.0f, 1.0f}, {1.0, 0.0}},
{{-1.0f, -1.0f, 1.0f}, {1.0, 1.0}},
{{ 1.0f, -1.0f, 1.0f}, {0.0, 1.0}},
// Back Face
{{-1.0f, -1.0f, -1.0f}, {1.0, 0.0}},
{{-1.0f, 1.0f, -1.0f}, {1.0, 1.0}},
{{ 1.0f, 1.0f, -1.0f}, {0.0, 1.0}},
{{ 1.0f, -1.0f, -1.0f}, {0.0, 0.0}},
// Top Face
{{-1.0f, 1.0f, -1.0f}, {0.0, 1.0}},
{{-1.0f, 1.0f, 1.0f}, {0.0, 0.0}},
{{ 1.0f, 1.0f, 1.0f}, {1.0, 0.0}},
{{ 1.0f, 1.0f, -1.0f}, {1.0, 1.0}},
// Bottom Face
{{-1.0f, -1.0f, -1.0f}, {1.0, 1.0}},
{{ 1.0f, -1.0f, -1.0f}, {0.0, 1.0}},
{{ 1.0f, -1.0f, 1.0f}, {0.0, 0.0}},
{{-1.0f, -1.0f, 1.0f}, {1.0, 0.0}},
// Right face
{{1.0f, -1.0f, -1.0f}, {1.0, 0.0}},
{{1.0f, 1.0f, -1.0f}, {1.0, 1.0}},
{{1.0f, 1.0f, 1.0f}, {0.0, 1.0}},
{{1.0f, -1.0f, 1.0f}, {0.0, 0.0}},
// Left Face
{{-1.0f, -1.0f, -1.0f}, {0.0, 0.0}},
{{-1.0f, -1.0f, 1.0f}, {1.0, 0.0}},
{{-1.0f, 1.0f, 1.0f}, {1.0, 1.0}},
{{-1.0f, 1.0f, -1.0f}, {0.0, 1.0}}
};
void SetupGeometry() {
/* Allocate and assign One Vertex Buffer Object to our handle */
glGenBuffers(1, vbo);
/* Bind our VBO as being the active buffer and storing vertex attributes (coordinates + colors) */
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
/* Copy the vertex data from plane to our buffer */
/* 12 * sizeof(GLfloat) is the size of the tetrahedrom array, since it contains 12 Vertex values */
glBufferData ( GL_ARRAY_BUFFER, 24 * sizeof ( struct Vertex ), plane, GL_STATIC_DRAW );
/* Specify that our coordinate data is going into attribute index 0, and contains three doubles per vertex */
/* Note stride = sizeof ( struct Vertex ) and pointer = ( const GLvoid* ) 0 */
glVertexAttribPointer ( ( GLuint ) 0, 3, GL_DOUBLE, GL_FALSE, sizeof ( struct Vertex ), ( const GLvoid* ) offsetof (struct Vertex,position) );
/* Enable attribute index 0 as being used */
glEnableVertexAttribArray(0);
/* Specify that our color data is going into attribute index 1, and contains three floats per vertex */
/* Note stride = sizeof ( struct Vertex ) and pointer = ( const GLvoid* ) ( 3 * sizeof ( GLdouble ) ) i.e. the size (in bytes)
occupied by the first attribute (position) */
glVertexAttribPointer ( ( GLuint ) 1, 3, GL_FLOAT, GL_FALSE, sizeof ( struct Vertex ), ( const GLvoid* ) offsetof(struct Vertex,texture) ); // bug );
/* Enable attribute index 1 as being used */
glEnableVertexAttribArray ( 1 );/* Bind our fourth VBO as being the active buffer and storing vertex attributes (texture) */
printf("vertex %d\n", offsetof(struct Vertex,position));
printf("texture %d\n", offsetof(struct Vertex,texture));
}
void SetupShaders(void) {
/* Read our shaders into the appropriate buffers */
vertexsource = filetobuf("plane/plane.vert");
fragmentsource = filetobuf("plane/plane.frag");
/* Assign our handles a "name" to new shader objects */
vertexshader = glCreateShader(GL_VERTEX_SHADER);
fragmentshader = glCreateShader(GL_FRAGMENT_SHADER);
/* Associate the source code buffers with each handle */
glShaderSource(vertexshader, 1, (const GLchar**)&vertexsource, 0);
glShaderSource(fragmentshader, 1, (const GLchar**)&fragmentsource, 0);
/* Compile our shader objects */
glCompileShader(vertexshader);
glCompileShader(fragmentshader);
/* Assign our program handle a "name" */
shaderprogram = glCreateProgram();
glAttachShader(shaderprogram, vertexshader);/* Attach our shaders to our program */
glAttachShader(shaderprogram, fragmentshader);
glBindAttribLocation(shaderprogram, 0, "in_Position"); /* Bind attribute 0 (coordinates) to in_Position and attribute 1 (colors) to in_Texture */
glBindAttribLocation(shaderprogram, 1, "in_Texture");
glLinkProgram(shaderprogram);/* Link our program, and set it as being actively used */
glUseProgram(shaderprogram);
}
void Render(int i) {
GLfloat angle;
glm::mat4 Projection = glm::perspective(45.0f, 1.0f, 0.1f, 100.0f);
angle = (GLfloat) (i % 360);
glm::mat4 View = glm::mat4(1.);
View = glm::translate(View, glm::vec3(0.f, 0.f, -5.0f));
View = glm::rotate(View, angle * -1.0f, glm::vec3(1.f, 0.f, 0.f));
View = glm::rotate(View, angle * 0.5f, glm::vec3(0.f, 1.f, 0.f));
View = glm::rotate(View, angle * 0.5f, glm::vec3(0.f, 0.f, 1.f));
glm::mat4 Model = glm::mat4(1.0);
glm::mat4 MVP = Projection * View * Model;
glUniformMatrix4fv(glGetUniformLocation(shaderprogram, "mvpmatrix"), 1, GL_FALSE, glm::value_ptr(MVP));
/* Bind our modelmatrix variable to be a uniform called mvpmatrix in our shaderprogram */
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDrawArrays(GL_QUADS, 0, 24);
/* Invoke glDrawArrays telling that our data consists of individual triangles */
}
int reverse = 1;
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
if ((key == GLFW_KEY_ESCAPE || key == GLFW_KEY_Q) && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
if ((key == GLFW_KEY_R) && action == GLFW_PRESS)
reverse = 1 - reverse; // togrls reverse from 0 to 1 to o to ...
}
int main( void ) {
int k = 0;
GLFWwindow* window;
if( !glfwInit() ) {
printf("Failed to start GLFW\n");
exit( EXIT_FAILURE );
}
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window) {
glfwTerminate();
printf("GLFW Failed to start\n");
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window); // IMPORTANT: Must be done so glew recognises OpenGL
glewExperimental = GL_TRUE;
int err = glewInit();
if (GLEW_OK != err) {
/* Problem: glewInit failed, something is seriously wrong. */
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
}
fprintf(stderr, "Glew done\n");
glfwSetKeyCallback(window, key_callback);
fprintf(stderr, "GL INFO %s\n", glGetString(GL_VERSION));
SetupGeometry();
SetupShaders();
int w, h, n, O;
char *filename = "plane/rock.bmp";
unsigned char * data = stbi_load(filename, &w, &h, &n, 0); //image data
if(data == NULL) {
print("Image not loaded");
const char *error = stbi_failure_reason();
printf("Failure reason %s\n", error);
exit(0);
}else{
print("Image loaded successfully");
}
printf("Image Stats %d %d %d\n", w, h, n);
// for(int d = 0; d < w * h * 3; d++)
// printf("img content: %i\n",data[d]);
printf (" first 4 bytes are: %i %i %i %i\n", data[ 0], data[ 1], data[ 2], data[ 3] );
GLuint tex;
glGenTextures(1, &tex);
Print("Texture");
Print(GL_TEXTURE0);
print((int) tex);
//glActiveTexture(GL_TEXTURE0);
/*
* To get the texture to activate, take the base texture GL_TEXTURE0 and add the value of the generated texture.
* This needs checking with more than one texture.
* beware of NIDIA specific.
*/
//glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
stbi_image_free(data); // free up image data
//glDisable(gl_te)
glEnable(GL_DEPTH_TEST);
glClearColor(0.0, 0.0, 0.0, 1.0);/* Make our background black */
while( !glfwWindowShouldClose(window) ) {// Main loop
Render(k);// OpenGL rendering goes here...
if(reverse)
k--;
else
k++;
Sleep(20);
glfwSwapBuffers(window);// Swap front and back rendering buffers
glfwPollEvents();
}
glfwTerminate();// Close window and terminate GLFW
exit( EXIT_SUCCESS );// Exit program
}
The vertex shader:
#version 330
precision highp float;
in vec3 in_Position;
in vec2 in_Texture;
// mvpmatrix is the result of multiplying the model, view, and projection matrices */
uniform mat4 mvpmatrix;
out vec2 UV;
void main(void) {
// Multiply the mvp matrix by the vertex to obtain our final vertex position
gl_Position = mvpmatrix * vec4(in_Position, 1.0);
UV = in_Texture;
}
Fragment shader:
#version 330
precision highp float;
in vec2 UV;
out vec3 color;
uniform sampler2D myTexture;
void main(void) {
color = texture(myTexture, UV).rgb;
}
This is input image:
This is output of the program:
There is some inconsistency in the data types you are using. The declaration of your struct uses doubles for both position and texture coordinates:
struct Vertex {
GLdouble position[3];
GLdouble texture[2];
};
During attribute setup, you're using different types:
glVertexAttribPointer ( ( GLuint ) 0, 3, GL_DOUBLE, GL_FALSE, sizeof ( struct Vertex ), ( const GLvoid* ) offsetof (struct Vertex,position) );
glVertexAttribPointer ( ( GLuint ) 1, 3, GL_FLOAT, GL_FALSE, sizeof ( struct Vertex ), ( const GLvoid* ) offsetof(struct Vertex,texture) ); // bug );
The texture coordinates are used as GL_FLOAT here. Also, you specify 3 components here, where the struct has only 2.
There's very rarely a good reason to use doubles for coordinates. OpenGL will use 32-bit precision internally anyway. So if you specify attributes as doubles, you will only add conversions, and use more memory.
To use float for everything, the struct should be declared like this:
struct Vertex {
GLfloat position[3];
GLfloat texture[2];
};
The attribute specification then looks like this:
glVertexAttribPointer ( ( GLuint ) 0, 3, GL_FLOAT, GL_FALSE, sizeof ( struct Vertex ), ( const GLvoid* ) offsetof (struct Vertex,position) );
glVertexAttribPointer ( ( GLuint ) 1, 2, GL_FLOAT, GL_FALSE, sizeof ( struct Vertex ), ( const GLvoid* ) offsetof(struct Vertex,texture) ); // bug );
The problem lies here:
/* Specify that our color data is going into attribute index 1,
and contains three floats per vertex */
/* Note stride = sizeof ( struct Vertex ) and
pointer = ( const GLvoid* ) ( 3 * sizeof ( GLdouble ) )
i.e. the size (in bytes) occupied by the first attribute
(position) */
glVertexAttribPointer ( ( GLuint ) 1, 3, GL_FLOAT, GL_FALSE, sizeof ( struct Vertex ), ( const GLvoid* ) offsetof(struct Vertex,texture) );
The vertex texture coordinate attribute has two elements, but you're telling OpenGL that there were 3 elements in succession. This obviously neither matches your vertex data nor the shader vertex attribute type. Adjust the element size to 2 and it should work. Oh, and you don't have to explicitly cast a number literal to GLuint.
I just wanna do the basics... give the shaders information from my application. I tried everything and nothing worked because I can never figure out what is new and what is deprecated in OpenGL
Vertex Shader:
#version 420 core
layout(location = 0) in vec2 p_rect;
layout(location = 1) in vec2 p_clipRect;
out vec2 texturePoint;
void main()
{
gl_Position = vec4( p_rect, 0.0, 1.0 );
texturePoint = p_clipRect;
}
Fragment Shader:
#version 420 core
uniform sampler2D p_texture;
in vec2 texturePoint;
out vec4 outColor;
void main()
{
outColor = texture( p_texture, texturePoint );
}
OpenGL Code:
glActiveTexture( GL_TEXTURE0 );
glBindTexture( GL_TEXTURE_2D, texture );
GLint texture_id( glGetUniformLocation( programId, "p_texture" ) );
glUniform1i( texture_id, texture );
// Element
static const GLushort element[] = { 0, 1, 2, 3 };
GLuint element_id;
glGenBuffers( 1, &element_id );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, element_id );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof( element ), element, GL_STATIC_DRAW );
// Vertex data
struct VertexInput
{
GLfloat m_rect[ 8 ];
GLfloat m_clipRect[ 8 ];
}
vertex;
// fill it up with data
GLfloat vertex_data[] =
{
-1.0f, -1.0f,
-1.0f, 1.0f,
1.0f, -1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
0.0f, 1.0f,
1.0f, 0.0f,
1.0f, 1.0f,
};
memcpy( &vertex, &vertex_data, sizeof( vertex_data ) );
// VBO
GLuint vertex_id;
glGenBuffers( 1, &vertex_id );
glBindBuffer( GL_ARRAY_BUFFER, vertex_id );
glBufferData( GL_ARRAY_BUFFER, sizeof(vertex), &vertex, GL_STATIC_DRAW );
glEnableVertexAttribArray( 0 );
glEnableVertexAttribArray( 1 );
glVertexAttribPointer( 0, 2, GL_FLOAT, GL_TRUE, 0, (void*)offsetof( VertexInput, m_rect ) );
glVertexAttribPointer( 1, 2, GL_FLOAT, GL_TRUE, 0, (void*)offsetof( VertexInput, m_clipRect ) );
// render the VBO
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, element_id );
glDrawElements( GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, (void*)0 );
// clean it up ;-)
glDisableVertexAttribArray( 0 );
glDisableVertexAttribArray( 1 );
The weird thing:
Case 1: If programId is the actual program id, I get texture_id = 0 but no information gets to the shader... nothing happens...
Case 2: If programId is anything other than the actual program id, I get texture_id = -1 but my code RENDERS the image perfectly (WEARD).
The thing is that... I know it's still wrong. I need to be able to give information to the shader and then render... I really don't know how the case 2 is working, but the fact is that I need to give more information to the shaders, like other textures, MVP matrix and so son. I can't do it. What is wrong? How do I give the correct value of my program id and get this information in the shader?
glActiveTexture( GL_TEXTURE0 );
...
glUniform1i( texture_id, texture );
Try this instead:
glActiveTexture( GL_TEXTURE0 + 0 );
...
glUniform1i( texture_id, 0 );
Sampler uniforms should be assigned the index of the desired texture unit, not the texture object ID.
I am trying to make basic triangle in opengl es 2, but whatever I do, it just doesn't seem to be working.. All I get is a white triangle. However, I think there might be a problem
when linking the program (that's I have disabled return from linking checking "if", otherwise it won't run at all). Also, when I run with the console, I get in the output "error: 1281". My code:
int loadShader(int type, char * shaderCode)
{
int length = strlen(shaderCode);
int shader = glCreateShader(type);
glShaderSource(shader, 1, (const char **) &shaderCode, NULL);
glCompileShader(shader);
return shader;
}
// Initializes the application data
int Init(void)
{
// Vertex shaders
char * vertexShaderCode =
"attribute vec4 vPosition; \n"
"void main() { \n"
" gl_Position = vPosition; \n"
"} \n";
char * fragmentShaderCode =
"precision mediump float; \n"
"void main() { \n"
" gl_FragColor = vec4(0.5, 0.5, 0.5, 1.0);\n"
"} \n";
GLuint vertexShader = loadShader(GL_VERTEX_SHADER, vertexShaderCode);
GLuint fragmentShader = loadShader(GL_FRAGMENT_SHADER, fragmentShaderCode);
GLint linked;
program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glBindAttribLocation(program, 0, "vPosition");
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &linked);
if(!linked)
{
GLint infoLen = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLen);
if(infoLen > 1)
{
char* infoLog = (char *) malloc(sizeof(char) * infoLen);
glGetProgramInfoLog(program, infoLen, NULL, infoLog);
free(infoLog);
}
glDeleteProgram(program);
//return 0;
}
// Basic GL setup
glClearColor (0.0, 0.0, 0.0, 1.0);
return GL_TRUE;
}
// Main-loop workhorse function for displaying the object
void Display(void)
{
// Clear the screen
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0, 0.0, 0.0, 1.0);
GLfloat vertices[] = {
-0.5f, 0.0f, -1.0f,
0.0f, 1.0f, -1.0f,
0.5f, 0.0f, -1.0f,
};
GLfloat colors[] = {
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
};
glUseProgram(program);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, colors);
glEnableVertexAttribArray(1);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
enable the vertex attrib array first and then pass the pointers...
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices);
glDrawArrays(GL_TRIANGLES, 0, 3);
Also you are sending colors in the "1" attrib array but there is no such attrib in the shader.