Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 4 years ago.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Improve this question
I'm trying to draw a red triangle in OpenGL using GLEW. Firstly, I have drawn a triangle at the center of screen. This is getting drawn correctly. Then, I am trying to use shaders to get a red triangle. But, I couldn't get a red triangle because my shader compilation is failing. What could be possibly wrong?
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
static unsigned int CompileShader(unsigned int type, const std::string& source)
{
unsigned int id = glCreateShader(type);
const char* src = source.c_str();
glShaderSource(id, 1, &src, nullptr);
glCompileShader(id);
int result;
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
if (result == GL_FALSE)
{
std::cout << "failed to compile shader" << std::endl;
}
return id;
}
static int CreateShader(const std::string& vertexShader, const std::string& fragmentShader)
{
unsigned int program = glCreateProgram();
unsigned int vs = CompileShader(GL_VERTEX_SHADER,vertexShader);
unsigned int fs = CompileShader(GL_FRAGMENT_SHADER,fragmentShader);
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
glValidateProgram(program);
glDetachShader(program,vs);
glDetachShader(program,fs);
glDeleteShader(vs);
glDeleteShader(fs);
return program;
}
int main(void)
{
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK) {
std::cout << "error..!!" << std::endl;
}
float positions[6] = {
-0.5f,-0.5f,
0.5f, -0.5f,
0.0f, 0.5f
};
unsigned int buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float),positions,GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
std::string vertexShader =
"#version 330 core\n"
"\n"
"layout(location=0) in vec4 position;\n"
"\n"
"void main()\n"
"{\n"
" gl_Position=position;\n"
"}\n";
std::string fragmentShader =
"#version 330 core\n"
"\n"
"layout(location=0) out vec4 color;\n"
"\n"
"void main()\n"
"{\n"
" color=vec4(1.0,0.0,0.0,1.0)\n"
"}\n";
unsigned int shader = CreateShader(vertexShader,fragmentShader);
glUseProgram(shader);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES,0,3);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
The shader compilation fails, because shader there is missing a semicolon after color=vec4(1.0,0.0,0.0,1.0) in the fragment.
If you print the shader info log, then you can find issues like this easily:
glCompileShader(id);
GLint status;
glGetShaderiv( id, GL_COMPILE_STATUS, &status );
if ( status == GL_FALSE )
{
GLint maxLen;
glGetShaderiv( id, GL_INFO_LOG_LENGTH, &maxLen );
std::vector< char >log( maxLen );
GLsizei len;
glGetShaderInfoLog( id, maxLen, &len, log.data() );
std::cout << "compile error:" << std::endl << log.data() << std::endl;
}
Further, I recommend to use Raw string literals:
std::string fragmentShader = R"(
#version 330 core
layout(location=0) out vec4 color;
void main()
{
color=vec4(1.0, 0.0, 0.0, 1.0);
}
)";
Related
I am just getting started with OpenGL, and have already hit a pretty frustrating bug with it. I've followed the learnopengl tutorial, encapsulating most stuff into a renderer class, which has uints for buffers and such. Here is the main code that does everything:
#include <gfx/gfx.h>
#include <gfx/gl.h>
#include <gfx/shaders.h>
#include <iostream>
void Renderer::init() {
vertex_shader_id = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader_id, 1, &vertex_shader, nullptr);
glCompileShader(vertex_shader_id);
GLint vertex_shader_status;
glGetShaderiv(vertex_shader_id, GL_COMPILE_STATUS, &vertex_shader_status);
if (vertex_shader_status == false) {
std::cout << "vsh compilation failed due to";
char vertex_fail_info_log[1024];
glGetShaderInfoLog(vertex_shader_id, 1024, nullptr, vertex_fail_info_log);
std::cout << vertex_fail_info_log << std::endl;
abort();
}
fragment_shader_id = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader_id, 1, &fragment_shader, nullptr);
glCompileShader(fragment_shader_id);
GLint fragment_shader_status;
glGetShaderiv(fragment_shader_id, GL_COMPILE_STATUS, &fragment_shader_status);
if (fragment_shader_status == false) {
std::cout << "fsh compilation failed due to";
char fragment_fail_info_log[1024];
glGetShaderInfoLog(fragment_shader_id, 1024, nullptr, fragment_fail_info_log);
std::cout << fragment_fail_info_log << std::endl;
abort();
}
shader_program = glCreateProgram();
glAttachShader(shader_program, vertex_shader_id);
glAttachShader(shader_program, fragment_shader_id);
glLinkProgram(shader_program);
GLint shader_program_status;
glGetProgramiv(shader_program, GL_LINK_STATUS, &shader_program_status);
if (shader_program_status == false) {
std::cout << "shprogram compilation failed due to";
char shader_program_fail_info_log[1024];
glGetShaderInfoLog(shader_program, 1024, nullptr, shader_program_fail_info_log);
std::cout << shader_program_fail_info_log << std::endl;
abort();
}
glUseProgram(shader_program);
glDeleteShader(vertex_shader_id);
glDeleteShader(fragment_shader_id);
}
void Renderer::draw(f32 verts[]) {
glUseProgram(shader_program);
glClearColor(1, 0, 0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glCreateVertexArrays(1, &vertex_array);
glBindVertexArray(vertex_array);
glCreateBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(f32), (void*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(vertex_array);
glUseProgram(shader_program);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
Here is shaders.h :
#ifndef SHADERS_H
#define SHADERS_H
const char* vertex_shader =
"#version 460 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main() {\n"
"gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\n\0";
const char* fragment_shader =
"#version 460 core\n"
"out vec4 FragColor;\n"
"void main() {\n"
"FragColor = vec4(0.0f, 1.0f, 0.0f, 1.0f);\n"
"}\n\0";
#endif
I cannot figure out for life of me, what is wrong. The red clear color shows up, but nothing else.
Looks like there's a problem with your draw method. The signature is void Renderer::draw(f32 verts[]) { Then later on you call glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); . The thing is, when you pass an array to a function, it decays to a pointer (Even though the declaration can make that look like it's not happening, which is very confusing). So in a function parameter, draw(f32 verts[]) is equivalent to draw(f32* verts). This question has some explanations on what's happening there.
Anyways, when you call sizeof(verts), you're just getting the number of bytes of a float pointer, not the number of bytes owned by verts. So you will not be specifying enough bytes when you call glBufferData() to create the triangle you are going for. The simple fix is to pass a length into your draw function, and then you would have something like
void Renderer::draw(f32* verts, int length) {
//...
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * length, verts, GL_STATIC_DRAW);
//...
}
Here is some docs on this particular function. It is possible there are other errors, but since you aren't blackscreening, and generally the code looks right, it is unlikely there's a bunch of invalid operations or anything.
To continue debugging after this, add the following to your code
#define GL_ERROR_CHECK() (log_error(__FILE__, __LINE__))
void log_error(const* file, int line) {
GLenum err;
while((err = glGetError()) != GL_NO_ERROR) {
std::cout << "GL error " << err << " in " << file << "at line " << line << std::endl;
}
}
and sprinkle GL_ERROR_CHECK() all over the place to see if any of the OpenGL calls were invalid.
I am working on compiling a simple openGL program in Xcode on my M1 Mac. When I build, It succeeds, but I get a nasty
2022-04-05 09:54:18.959203-0500 opengl[24908:835152] [default] error finding potential wrapper bundle for node <FSNode 0x100a09910> { isDir = ?, path = '/Users/liamwhite/Library/Developer/Xcode/DerivedData/opengl-awawpgevgzpjofbrfmzvucbfrzpp/Build/Products/Debug' }: Error Domain=NSOSStatusErrorDomain Code=-10811 "kLSNotAnApplicationErr: Item needs to be an application, but is not" UserInfo={_LSLine=1579, _LSFunction=wrapperBundleNodeForWrappedNode}
2022-04-05 09:54:18.959276-0500 opengl[24908:835152] [default] error finding potential wrapper bundle for node <FSNode 0x100a09910> { isDir = ?, path = '/Users/liamwhite/Library/Developer/Xcode/DerivedData/opengl-awawpgevgzpjofbrfmzvucbfrzpp/Build/Products/Debug' }: Error Domain=NSOSStatusErrorDomain Code=-10811 "kLSNotAnApplicationErr: Item needs to be an application, but is not" UserInfo={_LSLine=1579, _LSFunction=wrapperBundleNodeForWrappedNode}
2022-04-05 09:54:18.959308-0500 opengl[24908:835152] [default] error finding potential wrapper bundle for node <FSNode 0x100a09910> { isDir = ?, path = '/Users/liamwhite/Library/Developer/Xcode/DerivedData/opengl-awawpgevgzpjofbrfmzvucbfrzpp/Build/Products/Debug' }: Error Domain=NSOSStatusErrorDomain Code=-10811 "kLSNotAnApplicationErr: Item needs to be an application, but is not" UserInfo={_LSLine=1579, _LSFunction=wrapperBundleNodeForWrappedNode}
2022-04-05 09:54:19.019242-0500 opengl[24908:835152] [default] error finding potential wrapper bundle for node <FSNode 0x100a09910> { isDir = ?, path = '/Users/liamwhite/Library/Developer/Xcode/DerivedData/opengl-awawpgevgzpjofbrfmzvucbfrzpp/Build/Products/Debug' }: Error Domain=NSOSStatusErrorDomain Code=-10811 "kLSNotAnApplicationErr: Item needs to be an application, but is not" UserInfo={_LSLine=1579, _LSFunction=wrapperBundleNodeForWrappedNode}
2022-04-05 09:54:19.054172-0500 opengl[24908:835152] Metal API Validation Enabled
Program ended with exit code: 0
A potential fix is proposed in a similar SO post, but I am new to Xcode and the answer is too vague for me.
Below is my code, if it is of any consequence:
#include <iostream>
#include <string>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
static unsigned int CompileShader(unsigned int type, const std::string& source)
{
unsigned int id = glCreateShader(type);
const char* src = source.c_str();
glShaderSource(id, 1, &src, nullptr);
glCompileShader(id);
int result;
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
if(!result)
{
int length;
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
char* message = static_cast<char*>(alloca(length * sizeof(char))); // alloca is from C. it allows dynamic stack allocation!
glGetShaderInfoLog(id, length, &length, message);
std::cout << "Failed to compile " << (type == GL_VERTEX_SHADER ? "vertex" : "fragment") << " shader" << std::endl;
std::cout << message << std::endl;
return 0;
}
return id;
}
static unsigned int CreateShader(const std::string& vertexShader, const std::string& fragmentShader)
{
unsigned int program = glCreateProgram();
unsigned int vs = CompileShader(GL_VERTEX_SHADER, vertexShader);
unsigned int fs = CompileShader(GL_FRAGMENT_SHADER, fragmentShader);
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
glValidateProgram(program);
glDeleteShader(vs);
glDeleteShader(fs);
return program;
}
int main()
{
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
if(!glewInit())
return 0;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
float positions[6] = {
-0.5f, -0.5f,
0.0f, 0.5f,
0.5f, -0.5f
};
unsigned int vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
unsigned int buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), positions, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 2, 0);
std::string vertexShader =
"#version 330 core\n"
"layout(location = 0) in vec4 position;\n"
"void main()\n"
"{\n"
"gl_Position = position;\n"
"}\n";
std::string fragmentShader =
"#version 330 core\n"
"layout(location = 0) out vec4 color;\n"
"void main()\n"
"{\n"
"color = vec4(1.0, 0.0, 0.0, 0.0, 1.0);\n"
"}\n";
unsigned int shader = CreateShader(vertexShader, fragmentShader);
glUseProgram(shader);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
Searched Stack Overflow for similar questions in search of my solution , but it doesn't seem to be solved.
main.cpp :
#include"reader.h"
#include"window.h"
#include"shader.h"
int main() {
float vertices[] = {
-0.5f, -0.5f, 0.0f ,
0.5f, -0.5f, 0.0f ,
0.0f, 0.5f, 0.0f
};
Window window;
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
Shader shader;
shader.addShader("./src/shaders/basic.vtx",GL_VERTEX_SHADER);
shader.addShader("./src/shaders/basic.frg", GL_FRAGMENT_SHADER);
shader.compile();
shader.enable();
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices,GL_STATIC_DRAW);
GLint pos_in = glGetAttribLocation(shader.getProgram(), "pos_in");
if (pos_in < 0) {
std::cout << "pos_in not found\n";
}
glVertexAttribPointer(pos_in, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *)0);
glEnableVertexAttribArray(pos_in);
while (!window.closed()) {
window.update();
glDrawArrays(GL_TRIANGLES,0,3);
}
return 0;
}
shader.h :
#pragma once
#include<glad/glad.h>
#include<iostream>
#include<vector>
#include"reader.h"
class Shader {
std::vector<GLuint*> shaders;
GLuint program;
public :
GLuint& getProgram() {
return program;
}
Shader() {
program = glCreateProgram();
}
void addShader(const char * path, GLenum type) {
std::string data = ShaderReader(path).read_shader();
const char * chardata = data.c_str();
GLuint shader = glCreateShader(type);
glShaderSource(shader, 1, &chardata , nullptr);
glCompileShader(shader);
int success;
char buffer[512];
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success) {
glGetShaderInfoLog(shader, 512, NULL, buffer);
std::cout << buffer << std::endl;
return;
}
std::cout << "shader inserted into vector\n";
shaders.push_back(&shader);
}
void compile(){
for (int i = 0; i != shaders.size();i++) {
glAttachShader(program, *shaders[i]);
}
glLinkProgram(program);
glValidateProgram(program);
glUseProgram(program);
int status;
glGetProgramiv(program, GL_COMPILE_STATUS, &status);
char buffer[512];
if (!status) {
glGetProgramInfoLog(program,512,NULL,buffer);
std::cout << buffer << std::endl;
return;
}
std::cout << "shader compilation successful\n";
}
void enable() {
glUseProgram(program);
}
void disable() {
glUseProgram(0);
}
~Shader() {
for (int i = 0; i != shaders.size();i++) {
glDeleteShader(*shaders[i]);
}
}
};
vertex shader written in basic.vtx:
#version 400
layout (location = 0 ) in vec3 pos_in ;
void main(){
gl_Position = vec4(pos_in.x , pos_in.y , pos_in.z , 1.0f);
}
fragment shader written in basic.frg :
#version 400
out vec4 color;
void main(){
color = vec4(0.0f, 0.5f , 0.5f , 1.0f);
}
At the time of calling glGetAttribLocation , the vertex shader IS USING pos_in attrib to set gl_Position , yet it returns -1 .
Also the triangle is not rendered when calling glGetAttribLocation() ; or rendered white with direct attrib pointer values like 0 , 1 with an openGL 1281 error.
One thing that is definitely not valid is the shaders.push_back(&shader):
void addShader(const char * path, GLenum type) {
// ....
GLuint shader = glCreateShader(type);
// ....
shaders.push_back(&shader);
}
With the shaders.push_back(&shader) you push back the address of a local variable to the shaders vector. So the glAttachShader(program, *shaders[i]); will result in undefined behavior.
shader holds only an numeric id so there is no need to get a pointer to that, just change the std::vector<GLuint*> shaders to std::vector<GLuint> shaders, use shaders.push_back(shader) and replace all *shaders[i] with shaders[i]
The reason why you don't get an linking error is most likely because the content at the address you get from &shader is not overwritten before you do the glAttachShader(program, *shaders[i]), and that both entries in the shaders vector hold same address of the stack. The result of is that glAttachShader is called each time on the same id, so you bind only the fragement shader to the program.
I am getting an error when trying to use VAO's inside of SFML and not sure if it is SFML or it is my own opengl code
GLenum err = glewInit();
if (err != GLEW_OK)
{
std::cout << "NOT WORKING" << std::endl;
}
std::vector<sf::Vector3f> g_vertext_buffer_data;
g_vertex_buffer_data.push_back({ -1.0f, -1.0f, 0.0f });
g_vertex_buffer_data.push_back({1.0f, -1.0f, 0.0f});
g_vertex_buffer_data.push_back({ 0.0f, 1.0f, 0.0f });
const char* vertexShaderSource =
"#version 330\n\
in vec4 position;\
void main(void){\ gl_Position = position;\
}";
// compile fragment shader source
const GLchar* fragmentShaderSource =
"#version 330\n\
void main(void) {\
out vec4 fragcolor; fragcolor= vec4(1.0,1.0,1.0,1.0);\
}";
/* Creating Shader */
this->programId = glCreateProgram();
this->vId = glCreateShader(GL_VERTEX_SHADER);
this->fId = glCreateShader(GL_FRAGMENT_SHADER);
/* Get Shader Size */
int vertexShaderLength = strlen(vertexShaderSource);
int fragmentShaderLength = strlen(fragmentShaderSource);
/* Loading and binding shader */
glShaderSource(this->vId, 1, &vertexShaderSource, NULL);
glShaderSource(this->fId, 1, &fragmentShaderSource, NULL);
/* Compile Shaders */
glCompileShader(vId);
glCompileShader(fId);
/* Attach Shaders */
glAttachShader(this->programId, this->vId);
glAttachShader(this->programId, this->fId);
/* Linkg program */
glLinkProgram(this->programId);
/* Use and bind attribute */
glUseProgram(this->programId);
this->positionId = glGetAttribLocation(this->programId, "position");
glUseProgram(0);
/* VAO Time */
glGenVertexArrays(1, &this->vaoId);
glBindVertexArray(this->vaoId);
/* VBO Time assigning to VAO */
glGenBuffers(1, &this->vboId);
glBindBuffer(GL_ARRAY_BUFFER, this->vboId);
glBufferData(GL_ARRAY_BUFFER, g_vertex_buffer_data.size() * sizeof(sf::Vector3f), &g_vertex_buffer_data[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(this->positionId);
glVertexAttribPointer(this->positionId, 2, GL_FLOAT, GL_FALSE, sizeof(sf::Vector3f), 0);
/* Close out bindings */
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
while(1)
{
glUseProgram(this->programId);
glBindVertexArray(this->vaoId);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glUseProgram(0);
gameWindow.glPushStates();
}
The error code I get is: opengl error in user code (1282)
I have changed the size() issue that was brought up in the blBufferData() but still am getting the issue.
There is at least a problem with the size that is passed to glBufferData:
glBufferData(GL_ARRAY_BUFFER,
sizeof(g_vertex_buffer_data) * sizeof(sf::Vector3f),
g_vertex_buffer_data[0], GL_STATIC_DRAW);
sizeof(g_vertex_buffer_data) is equal to sizeof(std::vector<?>) which is the size of the vector object and not the size of the data contained. Try using
glBufferData(GL_ARRAY_BUFFER,
g_vertex_buffer_data.size() * sizeof(sf::Vector3f),
g_vertex_buffer_data[0], GL_STATIC_DRAW);
Another thing: In OpenGL 3.3 Core Profile there is no gl_FragColor variable. You will have to define an out variable.
Next: Your vertex shader seems to be empty. You have to write to gl_Position otherwise nothing will be shown.
Possible error codes for glGetAttribLocation are:
GL_INVALID_OPERATION
Which don't have a fixed value. Try to get the error string with gluErrorString() or take a look in the header to which of those 1282 maps.
• check your shader got compiled without error?
• check your shader got linked without error?
What type have positionId? All object id's must be GLuint type.
And btw allways enable shader compilation-linking error check, and debug will be more informative.
I do that in this way (OpenGL-ES 2.0):
m_nVertexShader = glCreateShader(GL_VERTEX_SHADER);
m_nPixelShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(m_nVertexShader, 1, &lpszVertexBuffer, NULL);
glShaderSource(m_nPixelShader, 1, &lpszFragmentBuffer, NULL);
glCompileShader(m_nVertexShader);
int iIsOk = 0;
glGetShaderiv(m_nVertexShader, GL_COMPILE_STATUS, &iIsOk);
if(!iIsOk)
{
GLint infoLen = 0;
glGetShaderiv(m_nVertexShader, GL_INFO_LOG_LENGTH, &infoLen);
if(infoLen > 1)
{
char* infoLog = (char*)malloc(sizeof(char) * infoLen);
glGetShaderInfoLog(m_nVertexShader, infoLen, NULL, infoLog);
QMessageBox::warning(this, QString("Error"),
QString(infoLog), QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
free(infoLog);
}
glDeleteShader(m_nVertexShader);
return;
}
glCompileShader(m_nPixelShader);
glGetShaderiv(m_nPixelShader, GL_COMPILE_STATUS, &iIsOk);
if(!iIsOk)
{
GLint infoLen = 0;
glGetShaderiv(m_nPixelShader, GL_INFO_LOG_LENGTH, &infoLen);
if(infoLen > 1)
{
char* infoLog = (char*)malloc(sizeof(char) * infoLen);
glGetShaderInfoLog(m_nPixelShader, infoLen, NULL, infoLog);
QMessageBox::warning(this, QString("Error"),
QString(infoLog), QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
free(infoLog);
}
glDeleteShader(m_nPixelShader);
return;
}
m_nProgram = glCreateProgram();
glAttachShader(m_nProgram, m_nVertexShader);
glAttachShader(m_nProgram, m_nPixelShader);
glBindAttribLocation(m_nProgram, 0, "rm_Vertex");
glLinkProgram(m_nProgram);
glGetProgramiv(m_nProgram, GL_LINK_STATUS, &iIsOk);
// Fail to pass status validation
if(!iIsOk)
{
GLint infoLen = 0;
glGetProgramiv(m_nProgram, GL_INFO_LOG_LENGTH, &infoLen);
if(infoLen > 1)
{
char* infoLog = (char*)malloc(sizeof(char) * infoLen);
glGetProgramInfoLog(m_nProgram, infoLen, NULL, infoLog);
QMessageBox::warning(this, QString("Error"),
QString(infoLog), QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Yes);
free(infoLog);
}
glDeleteProgram(m_nProgram);
return;
}
glUseProgram(m_nProgram);
As you use GLSL 3.3, fist you must specify fragment rendertarget output by calling
glBindFragDataLocation(this->programId, 0, "fragcolor");
Secondly your fragment shader must be like
"#version 330
out vec4 fragcolor;
void main(void) {
fragcolor= vec4(1.0,1.0,1.0,1.0);
}
The example of using this kind of shaders is on OpenGL 3.3 + GLSL 1.5 Sample.
I am following the 8Th edition and below is the code I modified from book. it does not give me what I want, but a blank window instead. I wonder what mistake(s) did I make during modifications?
below is the code I modified, hope anyone can point out the mistake.
#include <iostream>
#include <OpenGL/glu.h>
#include <OpenGL/gl3.h>
#include <GLUT/GLUT.h>
GLuint vaoNames[1];
GLuint bufferNames[1];
int vPosition = 0;
GLuint createProgram();
GLuint createShader(GLenum type, const char* src);
GLuint program;
void init()
{
glGenVertexArrays(1, vaoNames);
glBindVertexArray(vaoNames[0]);
GLfloat vertices[6][2] = {
{ -0.90, -0.90 }, // Triangle 1
{ 0.85, -0.90 },
{ -0.90, 0.85 },
{ 0.90, -0.85 }, // Triangle 2
{ 0.90, 0.90 },
{ -0.85, 0.90 }
};
glGenBuffers(1, bufferNames);
glBindBuffer(GL_ARRAY_BUFFER, bufferNames[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glUseProgram(createProgram());
glVertexAttribPointer(vPosition, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(vPosition);
}
void render()
{
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(vaoNames[0]);
glDrawArrays(GL_TRIANGLES, 0, 6);
glFlush();
}
GLuint createProgram()
{
GLuint program = glCreateProgram();
const char* vertexShaderSrc =
"#version 400 core \n"
"layout( location = 0 ) in vec4 vPosition; \n"
"void main() \n"
"{ \n"
"gl_Position = vPosition; \n"
"}";
GLuint vertexShader = createShader(GL_VERTEX_SHADER, vertexShaderSrc);
const char* fragmentShaderSrc =
"#version 400 core \n"
"out vec4 fColor; \n"
"void main() \n"
"{ \n"
"fColor = vec4( 0.0, 0.0, 1.0, 1.0 ); \n"
"}";
GLuint fragmentShader = createShader(GL_FRAGMENT_SHADER, fragmentShaderSrc);
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
return program;
}
GLuint createShader(GLenum type, const char* src){
GLuint shaderID = glCreateShader(type);
glShaderSource(shaderID, 1, &src, 0);
glCompileShader(shaderID);
return shaderID;
}
int main(int argc, char ** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA);
glutInitWindowSize(512, 512);
glutCreateWindow("8877");
init();
glutDisplayFunc(render);
glutMainLoop();
}
When you say 'there is no error during shader compilation and program linking', do you mean that the the program doesn't stop, or do you mean that you actually ran a different program and checked the results of glGetError() at various points, or fetched the compilation or linking log? Your program as is does no actual error checking, and OpenGL doesn't throw exceptions or produce error output as a matter of course. You have to actually request these things.
Simply because glCompileShader() doesn't generate an error doesn't mean your shader actually compiled. You need to be checking the compilation status of shaders and the link status of programs with code similar to this:
GLint compiled;
glGetShaderiv(newShader, GL_COMPILE_STATUS, &compiled);
if (!compiled) {
std::string log = getLog(newShader);
SAY(log.c_str());
throw std::runtime_error("Failed to compile shader " + log);
}
where getLog is
static std::string getLog(GLuint shader) {
std::string log;
GLint infoLen = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
if (infoLen > 1) {
char* infoLog = new char[infoLen];
glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
log = std::string(infoLog);
delete[] infoLog;
}
return log;
}
This is for checking shaders, and there are equivalent functions for checking the results and getting the logs for program linking. Unless you're calling them you have no guarantee that the shaders are compiling. Assuming you haven't made some simple mistake in the shader syntax, the most likely problem you're facing is a lack of support for OpenGL 4.x, which would cause the shaders to fail right off.