Im having two problems but one at a time. Im attempting to render a 3d cube but it looks like just a square.
The shader is:
#version 330
uniform mat4 mvp;
layout(location=0) in vec4 vPosition;
layout(location=1) in vec4 vColor;
out vec4 color;
void main() {
color = vColor;
gl_Position = mvp * vPosition;
}
The entirety of my main:
#include "Angel.h"
#include <gl/glew.h>
#include <glut.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <iostream>
using namespace std;
#define bool int /* if system does not support bool type */
#define false 0
#define true 1
#define M_PI 3.14159265358 /* if not in math.h */
int winWidth, winHeight;
float angle = 0.0, axis[3], trans[3];
bool trackingMouse = false;
float lastPos[3] = {0.0, 0.0, 0.0};
float aspect = 1.0;
int curx, cury;
int startX, startY;
int modelInit=1;
//the program object
GLuint program = 0;
glm::mat4 model;
typedef Angel::vec4 color4;
typedef Angel::vec4 point4;
const int NumVertices = 36; //(6 faces)(2 triangles/face)(3 vertices/triangle)
point4 points[NumVertices];
color4 colors[NumVertices];
enum { Xaxis = 0, Yaxis = 1, Zaxis = 2, NumAxes = 3 };
int Axis = Xaxis;
GLuint mvpUniform;
GLuint shaderaxis;
int Index = 0;
// Vertices of a unit cube centered at origin, sides aligned with axes
point4 vertices[8]={
point4(-0.5, -0.5, 0.5, 1.0),
point4(-0.5, 0.5, 0.5, 1.0),
point4(0.5, 0.5, 0.5, 1.0),
point4(0.5, -0.5, 0.5, 1.0),
point4(-0.5, -0.5, -0.5, 1.0),
point4(-0.5, 0.5, -0.5, 1.0),
point4(0.5, 0.5, -0.5, 1.0),
point4(0.5, -0.5, -0.5, 1.0)
};
// RGBA colors
color4 vertex_colors[8] = {
color4(0.0, 0.0, 0.0, 1.0), // black
color4(1.0, 0.0, 0.0, 1.0), // red
color4(1.0, 1.0, 0.0, 1.0), // yellow
color4(0.0, 1.0, 0.0, 1.0), // green
color4(0.0, 0.0, 1.0, 1.0), // blue
color4(1.0, 0.0, 1.0, 1.0), // magenta
color4(1.0, 1.0, 1.0, 1.0), // white
color4(0.0, 1.0, 1.0, 1.0) // cyan
};
// quad generates two triangles for each face and assigns colors to the vertices
void quad(int a, int b, int c, int d) {
colors[Index] = vertex_colors[a]; points[Index] = vertices[a]; Index++;
colors[Index] = vertex_colors[b]; points[Index] = vertices[b]; Index++;
colors[Index] = vertex_colors[c]; points[Index] = vertices[c]; Index++;
colors[Index] = vertex_colors[a]; points[Index] = vertices[a]; Index++;
colors[Index] = vertex_colors[c]; points[Index] = vertices[c]; Index++;
colors[Index] = vertex_colors[d]; points[Index] = vertices[d]; Index++;
}
// generate 12 triangles: 36 vertices and 36 colors
void colorcube(void) {
quad(1, 0, 3, 2);
quad(2, 3, 7, 6);
quad(3, 0, 4, 7);
quad(6, 5, 1, 2);
quad(4, 5, 6, 7);
quad(5, 4, 0, 1);
}
// OpenGL initialization
void init(void) {
colorcube();
// Load shaders and use the resulting shader program
GLuint program = InitShader("vshader36.glsl", "fshader36.glsl");
glUseProgram(program);
// Create a vertex array object
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
// Create and initialize a buffer object
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(points) + sizeof(colors), NULL, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(points), points);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(points), sizeof(colors), colors);
// set up vertex arrays
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
model = glm::translate(glm::mat4(1.0), glm::vec3(0.0, 0.0, -5.0));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(points)));
mvpUniform = glGetUniformLocation(program, "mvp");
glEnable(GL_DEPTH_TEST);
glClearColor(1.0, 1.0, 1.0, 1.0);
}
void trackball_ptov(int x, int y, int width, int height, float v[3]) {
float d, a;
/* project x, y onto a hemisphere centered within width, height , note z is up here*/
v[0] = (2.0*x - width) / width;
v[1] = (height - 2.0F*y) / height;
d = sqrt(v[0]*v[0] + v[1]*v[1]);
v[2] = cos((M_PI/2.0) * ((d < 1.0) ? d : 1.0));
a = 1.0 / sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
v[0] *= a;
v[1] *= a;
v[2] *= a;
}
void display() {
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glm::mat4 proj = glm::perspective(90.F, 1.F, 0.1F, 100.F);
glm::mat4 view = glm::translate(glm::mat4(1.0), glm::vec3(0.0, 0.0, 0.0)); //apply mouse translation
//view = glm::rotate(view, 0.2*mousediff.x, glm::vec3(0.0, 1.0, 0.0)); //apply mouse rotation
//view = glm::rotate(view, 0.2*mousediff.y, glm::vec3(1.0, 0.0, 0.0));
//model = glm::translate(glm::mat4(1.0), glm::vec3(0.0, 0.0, -5.0));
//glUniformMatrix4fv(mvpUniform, 1, false, glm::value_ptr(proj));
glUniformMatrix4fv(mvpUniform, 1, false, glm::value_ptr(proj*view*model));
//glUniformMatrix4fv(mvpUniform, 1, false, glm::value_ptr(model*view*proj));
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
glutSwapBuffers();
}
void keyboard(unsigned char key, int x, int y) {
switch(key) {
case 033: // Escape Key
case 'q': case 'Q':
exit(EXIT_SUCCESS);
break;
}
}
void mouseButton(int button, int state, int x, int y) {
if(button==GLUT_RIGHT_BUTTON) exit(0);
/* holding down left button allows user to rotate cube */
if(button==GLUT_LEFT_BUTTON)
switch(state) {
case GLUT_DOWN:
trackingMouse = true;
startX = x;
startY = y;
curx = x;
cury = y;
trackball_ptov(x, y, 512, 512, lastPos);
break;
case GLUT_UP:
trackingMouse = false;
angle = 0.0;
break;
}
}
void mouseMotion(int x, int y) {
float curPos[3], dx, dy, dz;
/* compute position on hemisphere */
if(trackingMouse) {
/* compute the change in position on the hemisphere */
trackball_ptov(x, y, 512, 512, curPos);
dx = curPos[0] - lastPos[0];
dy = curPos[1] - lastPos[1];
dz = curPos[2] - lastPos[2];
if (dx || dy || dz) {
/* compute theta and cross product */
angle = 90.0 * sqrt(dx*dx + dy*dy + dz*dz);
axis[0] = lastPos[1]*curPos[2] - lastPos[2]*curPos[1];
axis[1] = lastPos[2]*curPos[0] - lastPos[0]*curPos[2];
axis[2] = lastPos[0]*curPos[1] - lastPos[1]*curPos[0];
/* update position */
lastPos[0] = curPos[0];
lastPos[1] = curPos[1];
lastPos[2] = curPos[2];
}
float w = angle;
float x = axis[0];
float y = axis[1];
float z = axis[2];
glm::mat4 xform = glm::mat4((1.F - (2.F * ( y*y + z*z ))),(2.F * ( x*y - z*w )),( x*z + y*w ),0.F,
(2.F * ( x*y + z*w )),(1.F - (2.F * ( x*x + z*z ))),(2.F * ( y*z - x*w )),0.F,
(2.F * ( x*z - y*w )),(2.F * ( y*z + x*w )),(1.F - (2.F * ( x*x + y*y ))),0.F,
0.F,0.F,0.F,1.F);
model = xform*model;
}
glutPostRedisplay();
}
int main(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(512, 512);
glutCreateWindow("Color Cube");
glewInit();
init();
glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutIdleFunc(display);
glutMouseFunc(mouseButton);
glutMotionFunc(mouseMotion);
glutMainLoop();
return 0;
}
Here is the fshader36 file that was requested.
#version 150
in vec4 color;
out vec4 fColor;
void main()
{
fColor = color;
}
here is VSHADER
#version 330
uniform mat4 mvp;
layout(location=0) in vec4 vPosition;
layout(location=1) in vec4 vColor;
out vec4 color;
void main() {
color = vColor;
gl_Position = mvp * vPosition;
}
Related
I'm trying to change the position of triangle without using transformation function, By changing only the position of x each time,
this my code in main while loop
float MyPoints[] = { 0.1 , 0.2, 0.3, 0.4, 0.5 , 0.6, 0.7, 0.8, 0.9};
int offset = (-1, 1);
for (int i = 0; i < sizeof(MyPoints); i++) {
offset += MyPoints[i];
ourShader.Use();
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);// unbind
}
and this is in shader
out vec3 ourColor;
out vec2 TexCoord;
uniform vec4 offset;
void main()
{
gl_Position = vec4(position.x + offset, position.y, position.z, 1.0f);
ourColor = color;
TexCoord = texCoord;
}
Edit
this my code in main while loop
float offset = 1.0f;
float step = 0.001f; //move
int i=0;
// Loop until window closed (Game loop)
while (!glfwWindowShouldClose(mainWindow))
{
// Get + Handle user input events
glfwPollEvents();
//Render
// Clear the colorbuffer
glClearColor(0.0f, 0.1f, 0.2f, 1.0f);
//glPointSize(400.0f);
glClear(GL_COLOR_BUFFER_BIT);
// Call Shader Program
//Rendering the first triangle
GLuint program =ourShader.Program ; // program object from "ourShader"
GLint offset_loc = glGetUniformLocation(program, "offset");
float MyPoints[] = { -0.1 , -0.2,-0.3,-0.4,-0.5 ,-0.6,-0.7,-0.8,-0.9 };
int noPoints = sizeof(MyPoints) / sizeof(float);
ourShader.Use();
for (int i = 0; i < noPoints; i++) {
glUniform1f(offset_loc, MyPoints[i] + offset);
}
offset += step;
if (MyPoints[i] + offset >= 1.0f || MyPoints[i] + offset <= -1.0f)
step *= -1.0f;
//update uniform data
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(mainWindow);
glBindVertexArray(0);// unbind
}
and this is in shader
out vec3 ourColor;
out vec2 TexCoord;
uniform float offset;
void main()
{
gl_Position = vec4(position.x + offset, position.y, position.z, 1.0f);
ourColor = color;
TexCoord = texCoord;
}
the Edit code make an movement from (-1.0) till the middle to the end of the window
First of all the number of elements in the array is sizeof(MyPoints) / sizeof(float).
The type of the uniform variable offset has to be float:
uniform float offset;
You've to get the location of the uniform variable offset by glGetUniformLocation and to set the value of the uniform by e.g. glUniform1f:
GLuint program = ; // program object from "ourShader"
GLint offset_loc = glGetUniformLocation(program, "offset");
float MyPoints[] = { 0.1 , 0.2, 0.3, 0.4, 0.5 , 0.6, 0.7, 0.8, 0.9};
int noPoints = sizeof(MyPoints) / sizeof(float);
// bind vertex array
glBindVertexArray(VAO);
// install program
ourShader.Use();
float offset = -1.0f;
for (int i = 0; i < noPoints; i++) {
// set value of the uniform (after program is installed)
offset += MyPoints[i];
glUniform1f(offset_loc, offset);
// draw one triangle
glDrawArrays(GL_TRIANGLES, 0, 3);
}
glBindVertexArray(0);
If you want to make the triangles move, then you've to change the offset of each individual triangle in every frame. e.g.:
float offset = 0.0f;
float step = 0.01f;
while (!glfwWindowShouldClose(mainWindow))
{
// [...]
ourShader.Use();
glUniform1f(offset_loc, offset);
glDrawArrays(GL_TRIANGLES, 0, 3);
// [...]
// change offset
offset += step;
if (offset >= 1.0f || offset <= -1.0f)
step *= -1.0f; // reverse direction
}
Im trying to rotate plane from two triangles in shader.
everything goes fine except i cant understand what with the UV coordinates values happens when i applying rotation.
How i can perform this rotation with expected results?
this looks as UV coordinates interpolated independent for each triangle.
let pid, rotateYlocation;
let gl = canvas.getContext('webgl');
let values = document.querySelector('span')
let loader = new Image();
loader.crossOrigin = "anonymous";
loader.src = "https://i.imgur.com/G9H683l.jpg";
loader.onload = function() {
canvas.width = loader.width;
canvas.height = loader.height;
pid = gl.createProgram();
shader(`
float perspective = 1.0;
attribute vec2 coords;
uniform float rotateY;
varying vec2 uv;
void main(void) {
mat3 rotY = mat3(vec3( cos(rotateY), 0.0, sin(rotateY)),
vec3( 0.0, 1.0, 0.0),
vec3( -sin(rotateY), 0.0, cos(rotateY)));
vec3 p = vec3(coords.xy, 0.) * rotY;
uv = coords.xy.xy*0.5 + 0.5;
gl_Position = vec4(p / (1.0 + p.z * perspective), 1.0);
}
`, gl.VERTEX_SHADER);
shader(`
precision highp float;
uniform sampler2D texture;
varying vec2 uv;
void main(void) {
gl_FragColor = texture2D(texture, uv);
}
`, gl.FRAGMENT_SHADER);
gl.linkProgram(pid);
gl.useProgram(pid);
let array = new Float32Array([-1.0, -1.0, 1.0, -1.0, -1.0, 1.0,
-1.0, 1.0, 1.0, -1.0, 1.0, 1.0]);
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW);
let al = gl.getAttribLocation(pid, "coords");
gl.vertexAttribPointer(al, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(al);
let texture = gl.createTexture();
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true)
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, loader);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.uniform1i(gl.getUniformLocation(pid, "texture"), 0);
rotateYlocation = gl.getUniformLocation(pid, 'rotateY');
draw();
}
function draw() {
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
gl.clearColor(0, 0, 0, 0);
gl.uniform1f(rotateYlocation, rotateY.value/1000-0.5)
gl.drawArrays(gl.TRIANGLES, 0, 6);
values.textContent = `rotateY: ${(rotateY.value/1000-0.5).toFixed(3)}`;
}
function shader(src, type) {
let sid = gl.createShader(type);
gl.shaderSource(sid, src);
gl.compileShader(sid);
var message = gl.getShaderInfoLog(sid);
gl.attachShader(pid, sid);
if (message.length > 0) {
console.log(src.split('\n').map(function (str, i) {
return ("" + (1 + i)).padStart(4, "0") + ": " + str
}).join('\n'));
throw message;
}
}
<input type="range" id="rotateY" min="0" max="1000" value="500" onmousemove="draw()">
<span></span><br>
<canvas id="canvas" style="zoom:0.4"></canvas>
varying variables are interpolated in a perspective correct manner. gl_Position is a Homogeneous coordinates (x, y, z, w). For a perspective correct interpolation, the coordinate has to be set correctly.
When you do
gl_Position = vec4(p / (1.0 + p.z * perspective), 1.0)
then the perspective interpolation can not be performed correctly, because the coordinate is just a Cartesian coordinate (x, y, z, 1) and this results in a linear interpolation, because w=1.
For a detailed information of perspective correct interpolation see How exactly does OpenGL do perspectively correct linear interpolation?.
A homogeneous coordinate is transformed to the cartesian normalized device coordinate by a Perspective divide.
You have to set the clipspace coordinate, that coordinate before the perspective divide:
gl_Position = vec4(p, 1.0 + p.z * perspective);
let pid, rotateYlocation;
let gl = canvas.getContext('webgl');
let values = document.querySelector('span')
let loader = new Image();
loader.crossOrigin = "anonymous";
loader.src = "https://i.imgur.com/G9H683l.jpg";
loader.onload = function() {
canvas.width = loader.width;
canvas.height = loader.height;
pid = gl.createProgram();
shader(`
float perspective = 1.0;
attribute vec2 coords;
uniform float rotateY;
varying vec2 uv;
void main(void) {
mat3 rotY = mat3(vec3( cos(rotateY), 0.0, sin(rotateY)),
vec3( 0.0, 1.0, 0.0),
vec3( -sin(rotateY), 0.0, cos(rotateY)));
vec3 p = vec3(coords.xy, 0.) * rotY;
uv = coords.xy.xy*0.5 + 0.5;
gl_Position = vec4(p, 1.0 + p.z * perspective);
}
`, gl.VERTEX_SHADER);
shader(`
precision highp float;
uniform sampler2D texture;
varying vec2 uv;
void main(void) {
gl_FragColor = texture2D(texture, uv);
}
`, gl.FRAGMENT_SHADER);
gl.linkProgram(pid);
gl.useProgram(pid);
let array = new Float32Array([-1.0, -1.0, 1.0, -1.0, -1.0, 1.0,
-1.0, 1.0, 1.0, -1.0, 1.0, 1.0]);
gl.bindBuffer(gl.ARRAY_BUFFER, gl.createBuffer());
gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW);
let al = gl.getAttribLocation(pid, "coords");
gl.vertexAttribPointer(al, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(al);
let texture = gl.createTexture();
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true)
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, loader);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.uniform1i(gl.getUniformLocation(pid, "texture"), 0);
rotateYlocation = gl.getUniformLocation(pid, 'rotateY');
draw();
}
function draw() {
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
gl.clearColor(0, 0, 0, 0);
gl.uniform1f(rotateYlocation, rotateY.value/1000-0.5)
gl.drawArrays(gl.TRIANGLES, 0, 6);
values.textContent = `rotateY: ${(rotateY.value/1000-0.5).toFixed(3)}`;
}
function shader(src, type) {
let sid = gl.createShader(type);
gl.shaderSource(sid, src);
gl.compileShader(sid);
var message = gl.getShaderInfoLog(sid);
gl.attachShader(pid, sid);
if (message.length > 0) {
console.log(src.split('\n').map(function (str, i) {
return ("" + (1 + i)).padStart(4, "0") + ": " + str
}).join('\n'));
throw message;
}
}
<input type="range" id="rotateY" min="0" max="1000" value="500" onmousemove="draw()">
<span></span><br>
<canvas id="canvas" style="zoom:0.4"></canvas>
I have recently used a freetype library to read text files and followed some guide on how to display text in 2D.
I tried to extend the code to support 3D text rendering but i started having opengl related problems with it.
At certain angles the text picture starts to fade, and the whole axis on which the text is located starts to inherit its colour.
Fading;
Black Slice
All the related code is:
Drawing function (inherited from learnopengl.com)
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// Activate corresponding render state
glActiveTexture(GL_TEXTURE0);
glBindVertexArray(VAO);
glEnableVertexAttribArray(0);
scale /= RESOLUTION;
vec2 start(x, y);
// Iterate through all characters
std::string::const_iterator c;
for (c = text.begin(); c != text.end(); c++)
{
Character ch = Characters[*c];
if (*c == '\r' || (x-start.x > xMax && xMax != 0.0f))
{
y += ((ch.Advance >> 6) + 16) * scale ;
x = start.x;
continue;
}
GLfloat xpos = x + ch.Bearing.x * scale;
GLfloat ypos = y + (ch.Size.y - ch.Bearing.y) * scale;
GLfloat w = ch.Size.x * scale;
GLfloat h = ch.Size.y * scale;
// Update VBO for each character
GLfloat vertices[6][4] = {
{ xpos, ypos - h, 0.0, 0.0 },
{ xpos, ypos, 0.0, 1.0 },
{ xpos + w, ypos, 1.0, 1.0 },
{ xpos, ypos - h, 0.0, 0.0 },
{ xpos + w, ypos, 1.0, 1.0 },
{ xpos + w, ypos - h, 1.0, 0.0 }
};
// Render glyph texture over quad
glBindTexture(GL_TEXTURE_2D, ch.TextureID);
// Update content of VBO memory
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
// Render quad
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Now advance cursors for next glyph (note that advance is number of 1/64 pixels)
x += (ch.Advance >> 6) * scale; // Bitshift by 6 to get value in pixels (2^6 = 64)
}
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_BLEND);
Shader uniform initialization
ShaderBuilder::LoadShader(shader)->Add_mat4("projection", projection).Add_mat4("view", view).
Add_mat4("model", model).Add_vec3("textColor", color).Add_texture("text", 0);
Vertex Shader
#version 400 core
layout (location = 0) in vec4 vertex; //
out vec2 TexCoords;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
void main()
{
vec2 vertexGL = (vertex.xy - vec2(400,300)) / vec2(400,300);
vertexGL = vertex.xy;
vec4 position = projection * view * model * vec4(vertexGL.xy, 0.0, 1.0);
gl_Position = position / position.w;
TexCoords = vertex.zw;
}
Fragment Shader
#version 400 core
in vec2 TexCoords;
out vec4 color;
uniform sampler2D text;
uniform vec3 textColor;
void main()
{
vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, TexCoords).r);
color = vec4(textColor, 1.0) * sampled;
//color = vec4(1);
}
I finally found the mistake, for some unknown reason i thought normalizing my vertex coords after applying the matrix multiplication would be a good practice.
Apparently it isn't.
vec4 position = projection * view * model * vec4(vertexGL.xy, 0.0, 1.0);
gl_Position = position;// / position.w;
so as the commenting declares, this removed the mistake.
As the title says, I've been having troubles with normal mapping. First, a bit of background...
I was following TheCPlusPlusGuy's tutorials, using LWJGL, and ran into errors. I put a post on here, but it got no replies. I then moved into C++, and, once again, got back into normal mapping, and found more issues. The problem is, that when I move in the X-axis, the light appears to move as though I'm moving in the Y-axis. I've rendered the normal map texture, as a regular texture, and it works normally, so the bug therefore should be in the shaders.
I made a video of the bug, on YouTube here.
Here's the code:
vertex.vert:
#version 120
precision highp float;
varying vec2 texCoord;
varying vec3 position;
varying vec3 normal;
uniform vec3 lightPos;
varying vec3 tangentSurface2light;
varying vec3 tangentSurface2view;
mat3 getTangentMatrix(){
vec3 tangent;
vec3 v1 = cross(gl_Normal, vec3(0.0, 1.0, 0.0));
vec3 v2 = cross(gl_Normal, vec3(0.0, 0.0, 1.0));
if(length(v1) > length(v2)){
tangent = v1;
}else{
tangent = v2;
}
vec3 n = normalize(gl_NormalMatrix * gl_Normal);
vec3 t = normalize(gl_NormalMatrix * tangent);
vec3 b = cross(n, t);
mat3 mat = mat3(t.x, b.x, n.x,
t.y, b.y, n.y,
t.z, b.x, n.z);
return transpose(mat);
}
void main(){
mat3 tangent = getTangentMatrix();
texCoord = gl_MultiTexCoord0.xy;
gl_Position = ftransform();
position = vec3(gl_ModelViewMatrix * gl_Vertex);
normal = gl_NormalMatrix * gl_Normal;
vec3 vector = normalize(lightPos - position);
tangentSurface2light = tangent * vector;
vector = normalize(-position);
tangentSurface2view = tangent * vector;
}
fragment.frag:
#version 120
precision highp float;
varying vec2 texCoord;
uniform sampler2D texture;
uniform sampler2D normalMap;
varying vec3 position;
varying vec3 normal;
varying vec3 tangentSurface2light;
varying vec3 tangentSurface2view;
uniform vec3 lightPos;
uniform vec3 mambient;
uniform vec3 mdiffuse;
uniform vec3 mspecular;
uniform float shininess;
uniform vec3 lambient;
uniform vec3 ldiffuse;
uniform vec3 lspecular;
void main(){
float dist = length(position - lightPos);
float att = 1.0/(0.005*dist*dist);
vec3 tdiffuse = vec3(texture2D(texture, texCoord)) * mdiffuse;
vec3 ambient = mambient * lambient;
vec3 surf2light = normalize(tangentSurface2light);
vec3 norm = normalize(texture2D(normalMap, texCoord).xyz * 2.0 - 1.0);
float dcont = max(0.0, dot(norm, surf2light));
vec3 diffuse = dcont * tdiffuse * ldiffuse;
vec3 surf2view = normalize(tangentSurface2view);
vec3 reflection = reflect(-surf2light, norm);
float scont = pow(max(0.0, dot(surf2view, reflection)), shininess);
scont = max(0.0, dot(surf2view, reflection));
vec3 specular = scont * mspecular * lspecular;
gl_FragColor=vec4((ambient + diffuse + specular )* att, 1.0);
}
And just in case, main.cpp (Note functions.h is just the first person camera):
#include <iostream>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include "GLee.h"
#include <GL/gl.h>
#include <GL/glu.h>
#include <SDL/SDL_opengl.h>
#include <SDL/SDL_mouse.h>
#include <math.h>
#include <SDL/SDL_opengl.h>
#include <vector>
#include <string>
#include <algorithm>
#include <fstream>
#include <cstdio>
#include <cstdlib>
#include "functions.h"
//#include <SDL/SDL_video.h>
#define PI 3.14159265358979323846264338327
using namespace std;
unsigned int frame, texture, normalMap;
long double lPos = 0;
bool mousein = false;
#include "GLee.h"
void loadFile(const char* fn, string& str){
ifstream in(fn);
if(!in.is_open()){
cout<<"The file "<<fn<<"could not be opened!"<<endl;
return;
}
char tmp[300];
while(!in.eof()){
in.getline(tmp, 300);
str += tmp;
str += '\n';
}
}
unsigned int loadShader(string& source, unsigned int mode){
unsigned int id;
id = glCreateShader(mode);
const char* csource = source.c_str();
glShaderSource(id, 1, &csource, NULL);
glCompileShader(id);
char error[1000];
glGetShaderInfoLog(id, 1000, NULL, error);
cout<<"Compile Status: \n"<<error<<endl;
return id;
}
unsigned int vs, fs, program;
void initShader(const char* vname, const char* fname, unsigned int& program){//20:30 into vid...
string source;
loadFile(vname, source);
vs = loadShader(source, GL_VERTEX_SHADER);
source = "";
loadFile(fname, source);
fs = loadShader(source, GL_FRAGMENT_SHADER);
program = glCreateProgram();
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
glUseProgram(program);
}
void clean(const int& program){
glDetachShader(program, vs);
glDetachShader(program, fs);
glDeleteShader(vs);
glDeleteShader(fs);
glDeleteProgram(program);
}
void gluPerspective( GLdouble fovY, GLdouble aspect, GLdouble zNear, GLdouble zFar ){
const GLdouble pi = 3.1415926535897932384626433832795;
GLdouble fW, fH;
fH = tan( fovY / 360 * pi ) * zNear;
fW = fH * aspect;
glFrustum( -fW, fW, -fH, fH, zNear, zFar );
}
unsigned int loadTexture(const char* fileName){
//IMG_Init(0);
GLint numberOfColours = 0;
GLenum format;
SDL_Surface* img = IMG_Load(fileName);
img = SDL_DisplayFormatAlpha(img);
cout<<IMG_GetError();
//numberOfColours = img->format->BytesPerPixel;
if(!(&img)){
cout<<"Failed To Find Image!"<<endl;
}
cout<<"Reached load!"<<endl;
if(((img->w & (img->w - 1)) != 0)){cout<<"Warning: Image width not a power of 2!"<<endl;}
if(((img->h & (img->h - 1)) != 0)){cout<<"Warning: Image height not a power of 2!"<<endl;}
if(img->format->BytesPerPixel == 4){
format = GL_RGBA;
}else{
format = GL_RGB;
}
cout<<"GL_RGB: "<<GL_RGB<<"\nFormat: "<<format<<endl;
// SDL_PixelFormat pf;
//pf.palette = 0;
//pf.BitsPerPixel = 32;
//pf.BytesPerPixel = 4;
//pf.alpha = 255;
//pf.Rshift = pf.Rloss = pf.Gloss = pf.Bloss = pf.Aloss = pf.colorkey = 0;
//pf.Rmask = 0x000000ff;
//pf.Gshift = 8;
//pf.Gmask = 0x0000ff00;
//pf.Bshift = 16;
//pf.Bmask = 0x00ff0000;
//pf.Ashift = 24;
//pf.Amask = 0xff000000;
//SDL_Surface* glSurface = SDL_ConvertSurface(img, &pf, SDL_SWSURFACE);
unsigned int id;
glGenTextures(1, &id);
cout<<"ID: "<<id<<endl;
glBindTexture(GL_TEXTURE_2D, id);
cout<<"IMG Error: "<<IMG_GetError()<<endl;
cout<<"SDL Error: "<<SDL_GetError()<<endl;
glTexImage2D(GL_TEXTURE_2D, 0, format, img->w, img->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, img->pixels);
cout<<"IMG Error: "<<IMG_GetError()<<endl;
cout<<"SDL Error: "<<SDL_GetError()<<endl;
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP,GL_TRUE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16);
SDL_FreeSurface(img);
return id;
}
SDL_Surface* loadTextureData(const char* fileName){
SDL_Surface* tex;
if((tex = IMG_Load(fileName))){
cout<<"Texture Found! Tex: "<<fileName<<endl;
}
return tex;
}
void init(){
//glEnable(GL_CULL_FACE);
//glCullFace(GL_BACK);
const unsigned char* text = glGetString(GL_VERSION);
SDL_WM_GrabInput(SDL_GRAB_ON);
glEnable(GL_MULTISAMPLE);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 8);
SDL_WM_SetCaption("OGL!", "OGL!!");
//SDL_WM_IconifyWindow();
SDL_Surface* icon = loadTextureData("Logo.png");
SDL_WM_SetIcon(icon, NULL);
glClearColor(0.0, 0.0, 0.0, 1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, 1280.0/720.0, 0.1, 5000.0);
glMatrixMode(GL_MODELVIEW);
SDL_FreeSurface(icon);
texture = loadTexture("Moon.png");
normalMap = loadTexture("Normal Map.png");
SDL_ShowCursor(false);
initShader("vertex.vert", "fragment.frag", program);
}
void display(){
//frame++;
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glUniform1i(glGetUniformLocation(program, "texture"), 0);
glUniform1i(glGetUniformLocation(program, "normalMap"), 1);
glUniform3f(glGetUniformLocation(program, "lightPos"), 0, 0, 0);
glUniform3f(glGetUniformLocation(program, "mambient"), 0.2, 0.2, 0.2);
glUniform3f(glGetUniformLocation(program, "mdiffuse"), 0.6, 0.6, 0.6);
glUniform3f(glGetUniformLocation(program, "mspecular"), 1, 1, 1);
glUniform1f(glGetUniformLocation(program, "shininess"), 0);
glUniform3f(glGetUniformLocation(program, "lambient"), 0.2, 0.2, 0.2);
glUniform3f(glGetUniformLocation(program, "ldiffuse"), 0.4, 0.4, 0.4);
glUniform3f(glGetUniformLocation(program, "lspecular"), 1, 1, 1);
glUniform3f(glGetUniformLocation(program, "lightPos"), /*lPos*/0, 0, 0);
glLoadIdentity();
control(0.2, 0.2, mousein);
updateCamera();
//glTranslatef(0.0, 0.0, -6);
//glRotatef(frame, 0, 1, 0);
//glRotatef(90, 0, 1, 0);
/*glBegin(GL_TRIANGLES);
glScalef(15, 15, 15);
glColor4f(1.0, 0.0, 0.0, 1);
glVertex3f(0.0, 2.0, 0.0);
glColor4f(0.0, 1.0, 0.0, 1);
glVertex3f(-2.0, -2.0, 0.0);
glColor4f(0.0, 0.0, 1.0, 1);
glVertex3f(2.0, -2.0, 0.0);
glEnd();*/
//glRotatef(90, 0, 1, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, normalMap);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, normalMap);
glBegin(GL_QUADS);
glNormal3f(0.0, 0.0, 1.0);
glColor4f(1.0,1.0,1.0, 1.0);
glTexCoord2i(0, 0);
glVertex3f(-2.0, 2.0, 0.0);
glTexCoord2i(1, 0);
glVertex3f(-2.0, -2.0, 0.0);
glTexCoord2i(1, 1);
glVertex3f(2.0, -2.0, 0.0);
glTexCoord2i(0, 1);
glVertex3f(2.0, 2.0, 0.0);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
}
void update(){
frame++;
lPos = sin((180/PI)*(frame/10))*5;
}
int main(int args, char* argv[]){
SDL_Init(SDL_INIT_EVERYTHING);
IMG_Init(IMG_INIT_PNG);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 8);
SDL_Surface* screen = SDL_SetVideoMode(1280, 720, 32, SDL_SWSURFACE|SDL_OPENGL);
bool running = true;
Uint32 start;
SDL_Event event;
init();
while(running){
start = SDL_GetTicks();
while(SDL_PollEvent(&event)){
switch(event.type){
case SDL_QUIT:
running = false;
break;
case SDL_KEYDOWN:
switch(event.key.keysym.sym){
default:
break;
case SDLK_ESCAPE:
running = false;
break;
case SDLK_p:
mousein = false;
SDL_ShowCursor(SDL_ENABLE);
break;
}
break;
case SDL_KEYUP:
break;
case SDL_MOUSEBUTTONDOWN:
mousein = true;
SDL_ShowCursor(SDL_DISABLE);
break;
}
}
update();
display();
SDL_GL_SwapBuffers();
if(1000/60 > (SDL_GetTicks() - start)){
SDL_Delay(1000/60 - (SDL_GetTicks() - start));
}
}
clean(program);
SDL_Quit();
//cout << "Hello world!" << endl;
return 0;
}
I've been having trouble drawing a simple vertex-specified (box-like) teapot model using shaders with some input for translation and rotation. I've checked my gl code and matrices (object position on -z, camera at origin, etc) over and over and don't see why I'm still just getting a blank screen. to keep the code short, I've just put in the code for the basic cube of my model (once I at least get that I'll be fine).
namespace TeapotViewer{
class TeapotViewer{
private:
void intitialize();
void draw();
void reshape(int h, int w);
void keyHandle(unsigned char key, int x, int y);
void initCamera();
void reset();
void changeAxis();
void rotateOnAxis(float rot);
int createCube(int i);
public:
};
}
#include "TeapotViewer.h"
using namespace glm;
const int S_WIDTH = 800;
const int S_HEIGHT = 600;
const float FOV = 100;
const float P_NEAR = 0.2;
const float P_FAR = 20.0;
const float SPOUT_WIDTH = 0.025;
const float HANDLE_WIDTH = 0.15;
const float ZERO = 0.0;
const int numberOfVertices = 104;
const int noCubeSide = 10;
const int noCubeFace = 4;
const int noLine = 2;
mat4 modelxViewMatrix, projMatrix, viewMatrix, rotationMatrix, translationMatrix;
vec3 rotationAxis;
vec3 teapotPosition = vec3(0.0, 0.0,-3.0);
const vec3 cameraPosition = vec3(0.0, 0.0, 0.0);
const vec3 cameraDirection = vec3(0.0, 0.0, -1.0);
const vec3 cameraUp = vec3(0.0, 1.0, 0.0);
vec4 vertices[numberOfVertices];
GLuint refVertexArray;
GLuint refVertexBuffer;
GLuint refUniformModelxView;
GLuint refUniformProjection;
const vec4 body[] = {
vec4(-1.0,-1.0, 1.0, 1.0), vec4(-1.0, 1.0, 1.0, 1.0),
vec4( 1.0,-1.0, 1.0, 1.0), vec4( 1.0, 1.0, 1.0, 1.0),
vec4( 1.0,-1.0,-1.0, 1.0), vec4( 1.0, 1.0,-1.0, 1.0),
vec4(-1.0,-1.0,-1.0, 1.0), vec4(-1.0, 1.0,-1.0, 1.0)
};
const vec3 xAxis = vec3(1.0, 0.0, 0.0);
const vec3 yAxis = vec3(0.0, 1.0, 0.0);
const vec3 zAxis = vec3(0.0, 0.0, 1.0);
// draw callback
void draw(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
translationMatrix = translate(mat4(), teapotPosition);
modelxViewMatrix = viewMatrix*translationMatrix*rotationMatrix;
glUniformMatrix4fv(refUniformModelxView, 1, &modelxViewMatrix[0][0]);
glUniformMatrix4fv(refUniformProjection, 1, &projMatrix[0][0]);
void drawTeapot();
glutSwapBuffers();
}
void drawTeapot(){
int bufferIndex = 0;
// draw cube
glDrawArrays(GL_TRIANGLE_STRIP, bufferIndex, noCubeSide);
bufferIndex += noCubeSide;
glDrawArrays(GL_TRIANGLE_STRIP, bufferIndex, noCubeFace);
bufferIndex += noCubeFace;
glDrawArrays(GL_TRIANGLE_STRIP, bufferIndex, noCubeFace);
bufferIndex += noCubeFace;
// draw the axis of rotation
if (rotationAxis == xAxis){
glDrawArrays(GL_LINES, bufferIndex, noLine);
bufferIndex += noLine;
}
if (rotationAxis == yAxis){
bufferIndex += noLine;
glDrawArrays(GL_LINES, bufferIndex, noLine);
bufferIndex += noLine;
}
if (rotationAxis == zAxis){
bufferIndex += noLine*2;
glDrawArrays(GL_LINES, bufferIndex, noLine);
bufferIndex += noLine;
}
}
// reset back to the start
void reset(){
teapotPosition = vec3(0.0, 0.0,-3.0);
rotationMatrix = mat4();
}
void changeAxis(){
if(rotationAxis == xAxis)
rotationAxis = yAxis;
else
if(rotationAxis == yAxis)
rotationAxis = zAxis;
else
rotationAxis = xAxis;
}
void rotateOnAxis(float rot){
rotationMatrix = rotate(rotationMatrix, rot, rotationAxis);
}
// handle keypress
void keyHandle(unsigned char key, int x, int y){
switch(key){
case 033:
exit(EXIT_SUCCESS);
break;
case '0':
reset();
break;
case 'a':
teapotPosition = teapotPosition + vec3(-0.1, 0.0, 0.0);
break;
case 'd':
teapotPosition = teapotPosition + vec3(0.1, 0.0, 0.0);
break;
case 'w':
teapotPosition = teapotPosition + vec3(0.0, 0.1, 0.0);
break;
case 's':
teapotPosition = teapotPosition + vec3(0.0, -0.1, 0.0);
break;
case 'q':
teapotPosition = teapotPosition + vec3(0.0, 0.0, -0.1);
break;
case 'e':
teapotPosition = teapotPosition + vec3(0.0, 0.0, 0.1);
break;
case 'j':
changeAxis();
break;
case 'k':
rotateOnAxis(-5.0);
break;
case 'l':
rotateOnAxis(5.0);
break;
}
glutPostRedisplay();
}
void reshape(int h, int w){
glViewport(0, 0, h, w);
}
void initCamera(){
viewMatrix = lookAt(cameraDirection, cameraPosition, cameraUp);
projMatrix = perspective(FOV, (float)S_WIDTH/(float)S_HEIGHT, P_NEAR, P_FAR);
reset();
}
int createCube(int i){
// sides of the cube
vertices[i++] = body[0];
vertices[i++] = body[1];
vertices[i++] = body[2];
vertices[i++] = body[3];
vertices[i++] = body[4];
vertices[i++] = body[5];
vertices[i++] = body[6];
vertices[i++] = body[7];
vertices[i++] = body[0];
vertices[i++] = body[1];
// top
vertices[i++] = body[0];
vertices[i++] = body[2];
vertices[i++] = body[4];
vertices[i++] = body[6];
//bottom
vertices[i++] = body[1];
vertices[i++] = body[3];
vertices[i++] = body[5];
vertices[i++] = body[7];
std::cout << i << '\n';
return i;
}
int createAxes(int i){
// X axis
vertices[i++] = vec4( 2.0, 0.0, 0.0, 1.0);
vertices[i++] = vec4(-2.0, 0.0, 0.0, 1.0);
// Y axis
vertices[i++] = vec4( 0.0, 2.0, 0.0, 1.0);
vertices[i++] = vec4( 0.0,-2.0, 0.0, 1.0);
// Z axis
vertices[i++] = vec4( 0.0, 0.0, 2.0, 1.0);
vertices[i++] = vec4( 0.0, 0.0,-2.0, 1.0);
std::cout << i << '\n';
return i;
}
// Initialize
void initialize(){
// generate vertex data
int i = 0;
i = createCube(i);
i = createAxes(i);
if(i != numberOfVertices){
std::cout << "Error creating vertex data: check vertex count\n";
std::exit(0);
}
// set
initCamera();
// load shader and activate shader
GLuint refVertexShader = Angel::InitShader("Vertex_Shader.glsl", "Fragment_Shader.glsl");
glUseProgram(refVertexShader);
// create and activate a new vertex array object (vao)
glGenVertexArrays(1, &refVertexArray);
glBindVertexArray(refVertexArray);
// create and activate a new buffer array object in the vao
glGenBuffers(1, &refVertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, refVertexBuffer);
// load vertex data into the buffer array
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// load postion pipeline variable
GLuint refVec4Position = glGetAttribLocation(refVertexShader, "Position");
glEnableVertexAttribArray(refVec4Position);
glVertexAttribPointer(refVec4Position, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
// get pointers for uniform variables in shader program
refUniformModelxView = glGetUniformLocation(refVertexShader, "ModelxView");
refUniformProjection = glGetUniformLocation(refVertexShader, "Projection");
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glClearColor(0.0, 0.0, 0.0, 1.0);
}
int main(int argc, char* argv[]){
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(S_WIDTH, S_HEIGHT );
glutCreateWindow("TeapotViewer");
glewInit();
initialize();
glutDisplayFunc(draw);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyHandle);
glutMainLoop();
return 0;
}
vertex shader
#version 150
uniform mat4 ModelxView;
uniform mat4 Projection;
in vec4 Position;
void main()
{
gl_Position = Projection*ModelxView*Position;
}
fragment shader
#version 150
out vec4 fColor;
void main()
{
fColor = vec4(1.0, 1.0, 0.0, 1.0);
}
Not sure about this, as I'm not sure what's going on in Angel:: behind the scenes, but is it correct to output fColor from your fragment shader? I thought in glsl 150 it expects the special variable gl_FragColor, unless Angel does something specific to mitigate this.
I looked at this for a while but I don't see anything else that would cause a problem. Unfortunately I think if you're really stuck you might have to start writing a simpler example (no functions, just a straight rundown of initialization through rendering of a triangle).
Also make sure glGetError is called at least once per draw() loop to make sure it's not missing anything. Does Angel throw an exception on link/compilation failure?
Hmm, how about this:
viewMatrix = lookAt(cameraDirection, cameraPosition, cameraUp);
Is this the same lookAt as gluLookAt? In that function the prototype is (position, lookAtPoint, cameraUp), which is backwards of what you've got.