I need to code the fragment shader so that the triangle has a simple gradient effect. That is, so that its transparency decreases from left to right.
I tried this but it fails:
#version 120
uniform float startX = gl_FragCoord.x;
void main(void) {
gl_FragColor[0] = 0.0;
gl_FragColor[1] = 0.0;
gl_FragColor[2] = 1.0;
gl_FragColor[3] = startX / gl_FragCoord.x;
}
The full code:
#include <cstdlib>
#include <iostream>
using namespace std;
#include <GL/glew.h>
#include <SDL.h>
GLuint program;
GLint attribute_coord2d;
bool init_resources(void)
{
GLint compile_ok, link_ok = GL_FALSE;
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
const char* vs_source = R"(
#version 120
attribute vec2 coord2d;
void main(void) {
gl_Position = vec4(coord2d, 0.0, 1.0);
}
)";
glShaderSource(vs, 1, &vs_source, NULL);
glCompileShader(vs);
glGetShaderiv(vs, GL_COMPILE_STATUS, &compile_ok);
if (!compile_ok) {
cerr << "Error in vertex shader" << endl;
return false;
}
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
const char* fs_source = R"(
#version 120
uniform float startX = gl_FragCoord.x;
void main(void) {
gl_FragColor[0] = 0.0;
gl_FragColor[1] = 0.0;
gl_FragColor[2] = 1.0;
gl_FragColor[3] = startX / gl_FragCoord.x;
}
)";
glShaderSource(fs, 1, &fs_source, NULL);
glCompileShader(fs);
glGetShaderiv(fs, GL_COMPILE_STATUS, &compile_ok);
if (!compile_ok) {
cerr << "Error in fragment shader" << endl;
return false;
}
program = glCreateProgram();
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &link_ok);
if (!link_ok) {
cerr << "Error in glLinkProgram" << endl;
return false;
}
const char* attribute_name = "coord2d";
attribute_coord2d = glGetAttribLocation(program, attribute_name);
if (attribute_coord2d == -1) {
cerr << "Could not bind attribute " << attribute_name << endl;
return false;
}
return true;
}
void render(SDL_Window* window)
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program);
glEnableVertexAttribArray(attribute_coord2d);
GLfloat triangle_vertices[] = {
0.0, 0.8,
-0.8, -0.8,
0.8, -0.8,
};
glVertexAttribPointer(attribute_coord2d, 2, GL_FLOAT, GL_FALSE, 0, triangle_vertices);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(attribute_coord2d);
SDL_GL_SwapWindow(window);
}
void free_resources()
{
glDeleteProgram(program);
}
void mainLoop(SDL_Window* window)
{
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
while (true)
{
SDL_Event ev;
while (SDL_PollEvent(&ev))
{
if (ev.type == SDL_QUIT)
return;
}
render(window);
}
}
int main(int argc, char* argv[])
{
SDL_Init(SDL_INIT_VIDEO);
SDL_Window* window = SDL_CreateWindow("My First Triangle", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL);
SDL_GL_CreateContext(window);
GLenum glew_status = glewInit();
if (glew_status != GLEW_OK) {
cerr << "Error: glewInit: " << glewGetErrorString(glew_status) << endl;
return EXIT_FAILURE;
}
if (!init_resources())
return EXIT_FAILURE;
mainLoop(window);
free_resources();
return EXIT_SUCCESS;
}
How to do it right?
vYou can not initialize a uniform with gl_FragCoord.x. A uniform initialization is determined at link time.
uniform float startX = gl_FragCoord.x;
uniform float startX;
You have to set the unform with glUniform1f.
gl_FragCoord.xy are not the vertex coordinates. gl_FragCoord.xy are the window coordinate in pixels. You have to divide gl_FragCoord.xy by the size of the viewport:
#version 120
void main(void) {
gl_FragColor = vec4(0.0, 0.0, 0.0, gl_FragCoord.x / 640.0);
}
Or passing coord2d to the fragment shader:
#version 120
attribute vec2 coord2d;
varying vec2 coord;
void main(void) {
coord = coord2d;
gl_Position = vec4(coord2d, 0.0, 1.0);
}
#version 120
varying vec2 coord;
void main(void) {
float alpha = 2.0 / (1.0 - coord.y);
gl_FragColor = vec4(0.0, 0.0, 1.0, alpha);
}
Or use a color attribute:
#version 120
attribute vec2 coord2d;
attribute vec4 attrColor;
varying vec4 color;
void main(void) {
color = attrColor;
gl_Position = vec4(coord2d, 0.0, 1.0);
}
#version 120
varying vec4 color;
void main(void) {
gl_FragColor = color;
}
attribute_color = glGetAttribLocation(program, "attrColor");
GLfloat triangle_colors[] = {
0.0f, 0.0f, 1.0f, 0.5f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f, 1.0f
};
glEnableVertexAttribArray(attribute_color);
glVertexAttribPointer(attribute_color, 4, GL_FLOAT, GL_FALSE, 0, triangle_colors);
Related
I trying to learn OpenGl and now I wanted to make a simple red triangle on a black background with vertices and shaders. I copied the code from that YouTube video. I've changed a view things. That's my code:
#include "prec.h"
struct Vector2
{
float x, y;
};
struct TrianglePos
{
Vector2 a, b, c;
};
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 = (char*)alloca(length * sizeof(char));
glGetShaderInfoLog(id, length, &length, message);
std::cout << "Failed to compile shader, message: " << message << std::endl;
glDeleteShader(id);
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() {
if (!glfwInit())
return -1;
GLFWwindow *window = glfwCreateWindow(640, 480, "Sand Box GL", NULL, NULL);
if (!window) {
std::cout << "problems with window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
if (GLEW_OK != glewInit()) {
std::cout << "something with glew went wrong" << std::endl;
return -1;
}
TrianglePos trianglePos = {
-0.5f, -0.5f,
0.0f, 0.5f,
0.5f, -0.5f
};
unsigned int buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(trianglePos), &trianglePos, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), 0);
std::string vertexShader =
"#version 400 core\n"
"\n"
"layout(location = 0) in vec4 position;\n"
"\n"
"void main() \n"
"{\n"
" gl_Position = position;\n"
"}\n";
std::string fragmentShader =
"#version 400 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";
const char *versionGL;
versionGL = (char *) (glGetString(GL_VERSION));
std::cout << "openGl version: " << versionGL << std::endl;
if(GL_VERSION_4_0)
std::cout << "opengl 4.0 supported" << std::endl;
unsigned int shader = createShader(vertexShader, fragmentShader);
glUseProgram(shader);
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
and that's the precompiled header (prec.h): #pragma once
#ifndef GLEWINIT_PREC_H
#define GLEWINIT_PREC_H
#endif //GLEWINIT_PREC_H
#include "GL/glew.h"
#include <GLFW/glfw3.h>
#include <iostream>
the program prints that to the console ("OpenGL 4.0 supported" means that GL_VERSION_4_0 == true):
openGl version: 2.1 INTEL-14.5.22
opengl 4.0 supported
When I try to run it I get this error message from the shader Compiler for my vertex and fragment shader:
ERROR: 0:1: '' : version '400' is not supported
ERROR: 0:1: '' : syntax error: #version
ERROR: 0:3: 'layout' : syntax error: syntax error
When I change the #version 400 core to #version 120 I only get the syntax error for the layout. Because of that I think I messed up something with glew. What could I try?
Your system does not support OpenGL 4.0. It just supports OpenGL 2.1. See the output
openGl version: 2.1 INTEL-14.5.22
GLSL 1.20 corresponds to OpenGL 2.1. Downgrade the shader:
Vertex shader
#version 120
attribute vec4 position;
void main()
{
gl_Position = position;
}
Fragment shader
#version 120
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
Respectively using Raw string literals (C++11):
std::string vertexShader =
R"(#version 120
attribute vec4 position;
void main()
{
gl_Position = position;
}
)";
std::string fragmentShader =
R"(#version 120
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
)";
Here is a piece of code that I've been experimenting with:
#include <unistd.h>
#include "GL/gl3w.h"
#include "GLFW/glfw3.h"
#include <math.h>
#include <stdio.h>
#include <string.h>
class application {
private:
static void APIENTRY debug_callback(GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar* message,
GLvoid* userParam);
public:
application() {}
virtual ~application() {}
// virtual void run(application* the_app)
void run()
{
bool running = true;
// app = the_app;
if (!glfwInit())
{
fprintf(stderr, "Failed to initialize GLFW\n");
return;
}
init();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, info.majorVersion);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, info.minorVersion);
if (info.flags.robust)
{
glfwWindowHint(GLFW_CONTEXT_ROBUSTNESS, GLFW_LOSE_CONTEXT_ON_RESET);
}
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_SAMPLES, info.samples);
glfwWindowHint(GLFW_STEREO, info.flags.stereo ? GL_TRUE : GL_FALSE);
{
window = glfwCreateWindow(info.windowWidth, info.windowHeight, info.title, info.flags.fullscreen ? glfwGetPrimaryMonitor() : NULL, NULL);
if (!window)
{
fprintf(stderr, "Failed to open window\n");
return;
}
}
glfwMakeContextCurrent(window);
gl3wInit();
startup();
do
{
render(glfwGetTime());
glfwSwapBuffers(window);
glfwPollEvents();
running &= (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_RELEASE);
running &= (glfwWindowShouldClose(window) != GL_TRUE);
} while (running);
shutdown();
glfwDestroyWindow(window);
glfwTerminate();
}
virtual void init()
{
strcpy(info.title, "OpenGL SuperBible Example");
info.windowWidth = 800;
info.windowHeight = 600;
info.majorVersion = 4;
info.minorVersion = 5;
info.samples = 0;
info.flags.all = 0;
info.flags.cursor = 1;
}
virtual void startup() { }
virtual void render(double currentTime) { }
virtual void shutdown() { }
void setWindowTitle(const char * title) { glfwSetWindowTitle(window, title); }
virtual void onResize(int w, int h)
{
info.windowWidth = w;
info.windowHeight = h;
}
void getMousePosition(int& x, int& y)
{
double dx, dy;
glfwGetCursorPos(window, &dx, &dy);
x = static_cast<int>(floor(dx));
y = static_cast<int>(floor(dy));
}
public:
struct APPINFO
{
char title[128];
int windowWidth;
int windowHeight;
int majorVersion;
int minorVersion;
int samples;
union
{
struct
{
unsigned int fullscreen : 1;
unsigned int vsync : 1;
unsigned int cursor : 1;
unsigned int stereo : 1;
unsigned int debug : 1;
unsigned int robust : 1;
};
unsigned int all;
} flags;
};
protected:
APPINFO info;
static application * app;
GLFWwindow* window;
};
class tessellatedtri_app : public application
{
void init()
{
static const char title[] = "OpenGL SuperBible - Tessellated Triangle";
application::init();
memcpy(info.title, title, sizeof(title));
}
virtual void startup()
{
static const char * vs_source[] =
{
"#version 450 core \n"
"layout (location = 0) in vec4 offset; \n"
"layout (location = 1) in vec4 color; \n"
"out vec4 vs_color; \n"
"void main(void) \n"
"{ \n"
" const vec4 vertices[] = vec4[](vec4( 0.25, -0.25, 0.5, 1.0), \n"
" vec4(-0.25, -0.25, 0.5, 1.0), \n"
" vec4( 0.25, 0.25, 0.5, 1.0)); \n"
" \n"
" gl_Position = vertices[gl_VertexID] + offset; \n"
" vs_color = color; \n"
"} \n"
};
static const char * tcs_source[] =
{
"#version 450 core \n"
"layout (vertices = 3) out; \n"
" in vec4 vs_colors [];\n"
" out vec4 tcs_colors [3];\n"
"patch out vec4 patch_color; \n"
"void main(void) \n"
"{ \n"
// gl_TessLevelInner and gl_TessLevelOuter should only be set once
" if (gl_InvocationID == 0) \n"
" { \n"
" gl_TessLevelInner[0] = 3.0; \n"
" gl_TessLevelOuter[0] = 2.0; \n"
" gl_TessLevelOuter[1] = 2.0; \n"
" gl_TessLevelOuter[2] = 2.0; \n"
" } \n"
// " patch_color = vec4(.2, .3, .8); \n"
// " patch_color = vs_colors [gl_InvocationID]; \n"
// " tcs_colors[gl_InvocationID] = vs_colors[gl_InvocationID]; \n"
" gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; \n"
"} \n"
};
static const char * tes_source[] =
{
"#version 450 core \n"
"layout (triangles, equal_spacing, cw) in; \n"
// "patch in vec4 patch_color; \n"
// " out vec4 tes_color; \n"
"void main(void) \n"
"{ \n"
" gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position) + \n"
" (gl_TessCoord.y * gl_in[1].gl_Position) + \n"
" (gl_TessCoord.z * gl_in[2].gl_Position); \n"
// " tes_color = patch_color; \n"
"} \n"
};
static const char * fs_source[] =
{
"#version 450 core \n"
"in vec4 tes_color; \n"
"out vec4 color; \n"
"void main(void) \n"
"{ \n"
" color = vec4(0.2, 0.2, .4, 1.0); \n"
// " color = tes_color;"
"} \n"
};
program = glCreateProgram();
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, vs_source, NULL);
glCompileShader(vs);
GLuint tcs = glCreateShader(GL_TESS_CONTROL_SHADER);
glShaderSource(tcs, 1, tcs_source, NULL);
glCompileShader(tcs);
GLuint tes = glCreateShader(GL_TESS_EVALUATION_SHADER);
glShaderSource(tes, 1, tes_source, NULL);
glCompileShader(tes);
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, fs_source, NULL);
glCompileShader(fs);
glAttachShader(program, vs);
glAttachShader(program, tcs);
glAttachShader(program, tes);
glAttachShader(program, fs);
glLinkProgram(program);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}
virtual void render(double currentTime)
{
float color_var = ((float)sin(currentTime) + 1.f) / 2.f;
bg_color[0] = color_var;
glClearBufferfv(GL_COLOR, 0, bg_color);
glUseProgram(program);
float offset[] = {
(float) sin(currentTime) * .5f,
(float) cos(currentTime) * .5f,
(float) cos(currentTime) * .5f,
0.0f
};
glVertexAttrib4fv(0, offset);
fg_color[2] = color_var;
glVertexAttrib4fv(1, fg_color);
glDrawArrays(GL_PATCHES, 0, 3);
}
virtual void shutdown()
{
glDeleteVertexArrays(1, &vao);
glDeleteProgram(program);
}
private:
float bg_color[3] = {1.f, .7f, .8f};
float fg_color[3] = {.2f, .7f, .2f};
GLuint program;
GLuint vao;
};
int main(int argc, const char ** argv)
{
tessellatedtri_app *app = new tessellatedtri_app();
app->run();
delete app;
return 0;
}
I'm just trying to vary the color of the wireframe by time, but somehow I couldn't pass the color attribute through the stages after many attempts. Any suggestions? Thanks.
You need an input and an output for the attribute which you want to pass through in ever stage:
Vertex shader:
layout (location = 1) in vec4 color;
out vec4 vs_color;
void main(void)
{
vs_color = color;
// ...
}
In the Tessellation Control Shader the attribute can be passed through:
in vec4 vs_color[];
out vec4 tcs_colors[];
void main(void)
{
tcs_colors[gl_InvocationID] = vs_color[gl_InvocationID];
// ...
}
In the Tessellation Evaluation Shader you have to calculate the "tessellated" attribute from the per vertex input:
in vec4 tcs_colors[];
out vec4 tes_colors;
void main(void)
{
tes_colors = gl_TessCoord.x * tcs_colors[0] +
gl_TessCoord.y * tcs_colors[1] +
gl_TessCoord.z * tcs_colors[2];
// ...
}
Fragment shader:
in vec4 tes_colors;
I've tried to use this code for drawing triangle using VBO and shaders.
#include "gl.h"
#include <stdlib.h>
#include <GLFW/glfw3.h>
// utility libraries
#include "OGLShader.h"
#include "OGLProgram.h"
#include "OGLCommon.h"
#include "Shaders.h"
#include "OGLBuffer.h"
using namespace OpenGL;
GLFWwindow *window;
const int window_width = 800;
const int window_height = 600;
Shader **shaders;
Program *mainProgram;
int verticesCount = 3;
float triangle[] = {
0.0f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
};
int indicesCount = 3;
int indices[] = {
0, 1, 2
};
Buffer *verticesBuffer;
void init() {
glViewport(0, 0, window_width, window_height);
glClearColor(0, 0, 0, 1);
shaders = new OpenGL::Shader*[2];
// this code creates and compiles shaders, links shader program
shaders[0] = new OpenGL::Shader(GL_VERTEX_SHADER, OpenGL::vertexShaderSource);
shaders[1] = new OpenGL::Shader(GL_FRAGMENT_SHADER, OpenGL::fragmentShaderSource);
mainProgram = new OpenGL::Program(2, shaders);
mainProgram->use(); // use program
vertices_attrib_location = 0;
colors_attrib_location = 1;
glBindAttribLocation(mainProgram->getId(), vertices_attrib_location, "iVertex");
glBindAttribLocation(mainProgram->getId(), colors_attrib_location, "iColor");
verticesBuffer = new Buffer(GL_ARRAY_BUFFER);
verticesBuffer->data(verticesCount*3*sizeof(float), triangle, GL_STATIC_DRAW);
}
void deinit() {
delete verticesBuffer;
delete shaders[0];
delete shaders[1];
delete []shaders;
delete mainProgram;
}
void display() {
glClear(GL_COLOR_BUFFER_BIT);
glVertexAttrib3f(colors_attrib_location, 1, 0, 1);
verticesBuffer->bind();
glEnableVertexAttribArray(vertices_attrib_location);
glVertexAttribPointer(vertices_attrib_location, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
void update(double deltaTime) {
}
int main(int argc, char **argv) {
if (!glfwInit()) {
exit(1);
}
glfwWindowHint(GLFW_SAMPLES, 1);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
window = glfwCreateWindow(window_width, window_height, "Test", nullptr, nullptr);
if (!window) {
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
init();
double lastTime = 0.0;
while (!glfwWindowShouldClose(window)) {
display();
double curTime = glfwGetTime();
update(curTime - lastTime);
lastTime = curTime;
glfwSwapBuffers(window);
glfwPollEvents();
}
deinit();
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
Here is my shaders:
namespace OpenGL {
std::string vertexShaderSource =
"#version 120\n\
attribute vec3 iVertex;\
attribute vec3 iColor;\
varying vec3 oColor;\
void main(void)\n\
{\n\
oColor = iColor;\n\
\n\
gl_Position = vec4(iVertex, 1);\n\
}\n\
";
std::string fragmentShaderSource =
"#version 120\n\
varying vec3 oColor;\
varying vec2 oTexCoord;\n\
void main(void)\n\
{\n\
gl_FragColor = vec4(oColor, 1);\n\
}\n\
";
}
I tried to run this code both on Intel and ATI videocards, but everything that I see on the screen is empty black window. What I'm doing wrong?
this is my code so far(i write it from book(OpenGl Es 2.0 Programming Guide)):
i used precompiled Header name "pch.h"
#include"Pch.h"
typedef struct
{
GLuint programData;
}UserData;
void Render(ESContext* escontex);
int init(ESContext *escontex);
int main()
{
ESContext escontext;
UserData userData;
esInitContext(&escontext);
escontext.userData = &userData;
esCreateWindow(&escontext, L"Hello World!", 800, 600, ES_WINDOW_RGB);
esRegisterDrawFunc(&escontext, Render);
esMainLoop(&escontext);
}
int init(ESContext*escontex)
{
UserData *userData;
const char vShaderStr[] =
"attribute vec4 vPosition; \n"
"void main() \n"
"{ \n"
" gl_Position = vPosition; \n"
"} \n";
const char fShaderStr[] =
"precision meniump float; \n"
"void main() \n"
"{ \n"
"gl_FragColor(1.0,0.0.1.0.1.0); \n"
"}; \n";
GLuint programObject;
GLuint vertexShader;
GLuint fragmentShader;
vertexShader = LoadShader(GL_VERTEX_SHADER, vShaderStr);
fragmentShader = LoadShader(GL_FRAGMENT_SHADER, fShaderStr);
programObject = glCreateProgram();
if (programObject == 0) return 0;
glAttachShader(programObject, vertexShader);
glAttachShader(programObject, fragmentShader);
glBindAttribLocation(programObject, 0, "vPosition");
glLinkProgram(programObject);
userData->programData = programObject;
glUseProgram(userData->programData);
}
GLuint LoadShader(GLenum type, const char* shaderSrc)
{
GLuint shader;
GLint compile;
shader = glCreateShader(type);
if (shader == 0) return 0;
glShaderSource(shader,1 , &shaderSrc, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS,&compile);
return shader;
}
void Render(ESContext* escontex)
{
glViewport(0, 0, escontex->width, escontex->height);
glClear(GL_COLOR_BUFFER_BIT);
GLfloat vVertices[] = { 0.0f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f };
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vVertices);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, 3);
eglSwapBuffers(escontex->eglDisplay, escontex->eglSurface);
}
my problem is when i compile this i get error:"LoadShader Identifier not Found!"
what is the problem?
and for the second question is there anything wrong with this code?
You are calling LoadShader() before it is defined. To fix the issue put a function declaration at the top of your file.
#include"Pch.h"
typedef struct
{
GLuint programData;
}UserData;
void Render(ESContext* escontex);
int init(ESContext *escontex);
// this line here is new
GLuint LoadShader(GLenum type, const char* shaderSrc);
int main()
{
ESContext escontext;
...
I have a program like below:
#include <iostream>
#include <fstream>
#include <sstream>
#include <gl/glew.h>
#include <gl/freeglut.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace std;
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
GLuint prog, verShader, fragShader;
GLint attrPos, attrNor;
GLint uniModelView, uniProjection, uniModelViewTransposeInverse;
glm::mat4 modelMatrix, viewMatrix, projectionMatrix, MV, MVP;
glm::mat3 MVI;
const string loadFile(string name)
{
ifstream in(name.c_str(), ios::in);
if (in.fail()) {
cout << "File: '" << name << "' could not exist!!" << endl;
return "";
}
stringstream data;
data << in.rdbuf();
in.close();
return data.str();
}
GLuint createShader(GLenum type, const string name)
{
GLint isCompileOk;
GLuint shader;
string shaderText, shaderType;
const char *shaderSource;
switch(type)
{
case GL_VERTEX_SHADER:
shaderType = "GL_VERTEX_SHADER";
break;
case GL_FRAGMENT_SHADER:
shaderType = "GL_FRAGMENT_SHADER";
break;
}
shaderText = loadFile(name);
shaderSource = shaderText.c_str();
shader = glCreateShader(type);
glShaderSource(shader, 1, &shaderSource, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompileOk);
if (isCompileOk == GL_FALSE) {
char *shaderErr;
int errLength, errRetrieve;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &errLength);
shaderErr = new char [errLength + 1];
glGetShaderInfoLog(shader, errLength, &errRetrieve, shaderErr);
cout << "Compile '" << shaderType << "' error:" << endl;
cout << shaderErr << endl;
delete [] shaderErr;
return 0;
} else {
cout << "Compile '" << shaderType << "' ok!" << endl;
}
return shader;
}
bool makeShader()
{
GLint isLinkOk;
verShader = createShader(GL_VERTEX_SHADER, "vert.glsl");
fragShader = createShader(GL_FRAGMENT_SHADER, "frag.glsl");
prog = glCreateProgram();
glAttachShader(prog, verShader);
glAttachShader(prog, fragShader);
glLinkProgram(prog);
glGetProgramiv(prog, GL_LINK_STATUS, &isLinkOk);
if (isLinkOk == GL_FALSE) {
char *progErr;
int errLenght, errRetrieve;
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &errLenght);
progErr = new char[errLenght + 1];
glGetProgramInfoLog(prog, errLenght, &errRetrieve, progErr);
cout << "Link program error:" << endl;
cout << progErr << endl;
delete [] progErr;
return false;
} else {
cout << "Link program Ok!" << endl;
}
attrPos = glGetAttribLocation(prog, "position");
uniModelView = glGetUniformLocation(prog, "ModelViewMatrix");
uniProjection = glGetUniformLocation(prog, "ProjectionMatrix");
uniModelViewTransposeInverse = glGetUniformLocation(prog, "ModelViewTransposeInverseMatrix");
return true;
}
float vertexs[] = {
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f,
-1.0f, -1.0f, 1.0f
};
unsigned short indicates[] = {
0, 1, 2,
2, 3, 0
};
GLuint vao, vbo, ibo;
void display()
{
MV = viewMatrix * modelMatrix;
MVP = projectionMatrix * MV;
MVI = glm::transpose(glm::inverse(glm::mat3(MV)));
glUseProgram(prog);
glUniformMatrix4fv(uniModelView, 1, GL_FALSE, glm::value_ptr(MV));
glUniformMatrix3fv(uniModelViewTransposeInverse, 1, GL_FALSE, glm::value_ptr(MVI));
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, sizeof(indicates)/sizeof(unsigned short), GL_UNSIGNED_SHORT, 0);
glutSwapBuffers();
}
void reshape(int w, int h)
{
glViewport(0, 0, w, h);
projectionMatrix = glm::perspective(45.0f, float(w)/h, 0.1f, 1000.0f);
glUseProgram(prog);
glUniformMatrix4fv(uniProjection, 1, GL_FALSE, glm::value_ptr(projectionMatrix));
}
void idle()
{
glutPostRedisplay();
}
void Init()
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepth(1.0);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
modelMatrix = glm::mat4(1.0f);
viewMatrix = glm::lookAt(
glm::vec3(0.0f, 5.0f, 10.0f),
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(0.0f, 1.0f, 0.0f)
);
projectionMatrix = glm::mat4(1.0f);
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexs), vertexs, GL_STATIC_DRAW);
glVertexAttribPointer(attrPos, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, 0);
glEnableVertexAttribArray(attrPos);
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indicates), indicates, GL_STATIC_DRAW);
glBindVertexArray(0);
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
glutCreateWindow("Rectangle!");
if (glewInit() != GLEW_OK) {
cout << "glewInit() fail!" << endl;
return -1;
}
if (!makeShader()) {
cout << "makeShader() error!!" << endl;
return -1;
}
Init();
reshape(WINDOW_WIDTH, WINDOW_HEIGHT);
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutIdleFunc(idle);
glutMainLoop();
return 0;
}
when i adds VAO buffer, freeglut going to crash in glutMainLoop(), if i removes glGenVertexArrays call (of couse, removed what relatives to VAO too), it run ok, so my guess is problem in freeglut with glGenVertexArrays.
Question: What is my problem?
ps: My graphic cal support opengl 2.1, i use Visual Studio 2008.
Update: With VAO, above program work well but only crash when i close freeglut window.
Update shader: My shaders is very simple:
Vertex shader:
#version 120
attribute vec3 position;
// attribute vec3 normal;
uniform mat4 ModelViewMatrix;
uniform mat3 ModelViewTransposeInverseMatrix;
uniform mat4 ProjectionMatrix;
void main(void)
{
gl_Position = ProjectionMatrix * ModelViewMatrix * vec4(position, 1.0);
}
Fragment shader:
#version 120
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
glVertexAttribPointer(attrPos, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, 0);
Your vertex data is tightly packed. Use a stride of 0 instead of sizeof(float) * 3.
My graphic cal support opengl 2.1
Also, VAOs only became core in 3.0. You should check for ARB_vertex_array_object support before using that functionality.