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.
Related
I am drawing this texture using opengl and rust. But for some reason the image has border around it when I draw away from the top left. I think there is something wrong with matrix / viewport. Not entirely sure.
let width = 1280; // Window is initialised to these values. Hard coded for context.
let height = 720;
unsafe {
gl::Viewport(0, 0, width, height);
}
let orth = cgmath::ortho::<f32>(0.0, width as f32, height as f32, 0.0, -1.00, 100.0)
unsafe {
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_BORDER as i32);
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_BORDER as i32);
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as i32);
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32);
let border_colour = [0.9, 0.2, 0.5, 1.0];
gl::TexParameterfv(gl::TEXTURE_2D, gl::TEXTURE_BORDER_COLOR, border_colour.as_ptr());
gl::TexImage2D(
gl::TEXTURE_2D,
0,
gl::RGBA as i32,
img.width as i32,
img.height as i32,
0,
gl::RGBA,
gl::UNSIGNED_BYTE,
data.as_ptr() as *const c_void,
);
gl::GenerateMipmap(gl::TEXTURE_2D);
}
Before Drawing the texture, I clear the display
pub fn clear_frame_buffer() {
unsafe {
gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
gl::ClearColor(0.0, 0.0, 0.0, 1.0);
}
}
Drawing the texture:
pub fn draw_quad(tex: &Texture2D, program : &Program, mesh : &Mesh, projection : &Matrix4<f32>, position : Vector3<f32>) {
program.bind();
mesh.vao.bind();
tex.bind();
if let Some(location) = program.get_uniform_location("view") {
let camera_transform = Matrix4::<f32>::identity() * Matrix4::from_scale(1.0);
program.set_matrix(location, &[camera_transform]);
}
if let Some(location) = program.get_uniform_location("projection") {
program.set_matrix(location, &[*projection]);
}
if let Some(location) = program.get_uniform_location("model") {
let model = {
let translate = Matrix4::<f32>::from_translation(position);
let (w, h) = tex.get_dimensions();
let scale = Matrix4::<f32>::from_nonuniform_scale(w as f32, h as f32, 1.0);
translate * scale
};
program.set_matrix(location, &[model]);
}
let count = mesh.count as i32;
unsafe {
gl::DrawArrays(gl::TRIANGLES, 0, count);
}
}
Then I move the texture
I know the pink is coming from my color text param. But I shouldn't be able to see it? I should be only drawing the image and not the border.
let quad_vertices: [f32; 30] = [
// Positions // Texcoords
1.0, -1.0, 0.0, 1.0, 0.0,
-1.0, -1.0, 0.0, 0.0, 0.0,
-1.0, 1.0, 0.0, 0.0, 1.0,
1.0, 1.0, 0.0, 1.0, 1.0,
1.0, -1.0, 0.0, 1.0, 0.0,
-1.0, 1.0, 0.0, 0.0, 1.0,
];
Vertex Shader
#version 330 core
layout (location = 0) in vec3 vertex;
layout (location = 2) in vec2 texcoords;
out vec2 TexCoords;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
TexCoords = texcoords;
gl_Position = projection * view * model * vec4(vertex.xy, 0.0, 1.0);
}
Fragment Shader
#version 330 core
in vec2 TexCoords;
out vec4 color;
uniform sampler2D image;
void main()
{
color = texture(image, TexCoords);
}
I have been experimenting with batched sprite rendering, and I've got a solution that works well on my desktop PC. However, trying it on my integrated Intel UHD 620 laptop I get the following performance warnings:
[21:42:03 error] OpenGL: API - Performance - Recompiling fragment shader for program 27
[21:42:03 error] OpenGL: API - Performance - multisampled FBO 0->1
Presumably because of the source of these performance warnings, frames that take 1-2 milliseconds on my dedicated graphics card machine are about 100 milliseconds on my laptop.
Here is my renderer code:
BatchedSpriteRenderer::BatchedSpriteRenderer(ResourceManager &resource_manager)
: resource_manager(&resource_manager),
max_sprites(100000),
vertex_array(std::make_unique<VertexArray>()),
vertex_buffer(std::make_unique<VertexBuffer>())
{
resource_manager.load_shader("batched_texture",
"shaders/texture_batched.vert",
"shaders/texture.frag");
std::vector<unsigned int> sprite_indices;
for (int i = 0; i < max_sprites; ++i)
{
unsigned int sprite_number = i * 4;
sprite_indices.push_back(0 + sprite_number);
sprite_indices.push_back(1 + sprite_number);
sprite_indices.push_back(2 + sprite_number);
sprite_indices.push_back(2 + sprite_number);
sprite_indices.push_back(3 + sprite_number);
sprite_indices.push_back(0 + sprite_number);
}
element_buffer = std::make_unique<ElementBuffer>(sprite_indices.data(), max_sprites * 6);
VertexBufferLayout layout;
layout.push<float>(2);
layout.push<float>(2);
layout.push<float>(4);
vertex_array->add_buffer(*vertex_buffer, layout);
}
void BatchedSpriteRenderer::draw(const std::string &texture,
const std::vector<glm::mat4> &transforms,
const glm::mat4 &view)
{
vertex_array->bind();
auto shader = resource_manager->shader_store.get("batched_texture");
shader->bind();
std::vector<SpriteVertex> vertices;
vertices.reserve(transforms.size() * 4);
for (const auto &transform : transforms)
{
glm::vec4 transformed_position = transform * glm::vec4(0.0, 1.0, 1.0, 1.0);
vertices.push_back({glm::vec2(transformed_position.x, transformed_position.y),
glm::vec2(0.0, 1.0),
glm::vec4(1.0, 1.0, 1.0, 1.0)});
transformed_position = transform * glm::vec4(0.0, 0.0, 1.0, 1.0);
vertices.push_back({glm::vec2(transformed_position.x, transformed_position.y),
glm::vec2(0.0, 0.0),
glm::vec4(1.0, 1.0, 1.0, 1.0)});
transformed_position = transform * glm::vec4(1.0, 0.0, 1.0, 1.0);
vertices.push_back({glm::vec2(transformed_position.x, transformed_position.y),
glm::vec2(1.0, 0.0),
glm::vec4(1.0, 1.0, 1.0, 1.0)});
transformed_position = transform * glm::vec4(1.0, 1.0, 1.0, 1.0);
vertices.push_back({glm::vec2(transformed_position.x, transformed_position.y),
glm::vec2(1.0, 1.0),
glm::vec4(1.0, 1.0, 1.0, 1.0)});
}
vertex_buffer->add_data(vertices.data(),
sizeof(SpriteVertex) * vertices.size(),
GL_DYNAMIC_DRAW);
shader->set_uniform_mat4f("u_view", view);
shader->set_uniform_1i("u_texture", 0);
resource_manager->texture_store.get(texture)->bind();
glDrawElements(GL_TRIANGLES, transforms.size() * 6, GL_UNSIGNED_INT, 0);
}
Hopefully my abstractions should be fairly self explanatory. Each of the abstraction classes (VertexArray, VertexBuffer, ElementBuffer,VertexBufferLayout) manage the lifetime of their equivalent OpenGL object.
Here are the shaders being used:
texture_batched.vert
#version 430 core
layout(location = 0)in vec2 v_position;
layout(location = 1)in vec2 v_tex_coord;
layout(location = 2)in vec4 v_color;
out vec4 color;
out vec2 tex_coord;
uniform mat4 u_view;
void main()
{
tex_coord = v_tex_coord;
gl_Position = u_view * vec4(v_position, 0.0, 1.0);
color = v_color;
}
texture.frag
#version 430 core
in vec4 color;
in vec2 tex_coord;
out vec4 frag_color;
uniform sampler2D u_texture;
void main()
{
frag_color = texture(u_texture, tex_coord);
frag_color *= color;
}
What's causing these performance issues, and how can I fix them?
EDIT: I completely forgot to mention that the actual image rendered with this is completely messed up, I'll try and grab a screenshot of it working correctly when I get to my desktop PC, but here's what the broken version looks like:
It should be a neat grid of 200x200 white circles.
EDIT 2: I tried it on another computer, this time with a GTX 1050 Ti, and it is also broken. No error messages or warnings this time. The warning may have been unrelated.
It ended up being unrelated to OpenGL, as far as I can see.
In the draw function, I create a vector called vertices, then put all the vertices in it. For some reason, when I recreate that vector every frame the following push_back calls aren't properly adding to the vector. The members of the SpriteVertex structs were getting mixed up. As such, instead of the correct layout:
pos tex_coord color
pos tex_coord color
pos tex_coord color
pos tex_coord color
It was being filled in the following layout:
pos tex_coord color
tex_coord pos color
tex_coord pos color
tex_coord pos color
Or something to that effect, at least.
I changed it so that the vertices vector is a member of the BatchedSpriteRenderer class, reserving space for the maximum possible number of vertices.
void BatchedSpriteRenderer::draw(const std::string &texture,
const std::vector<glm::mat4> &transforms,
const glm::mat4 &view)
{
vertex_array->bind();
auto shader = resource_manager->shader_store.get("batched_texture");
shader->bind();
for (unsigned int i = 0; i < transforms.size(); ++i)
{
const auto &transform = transforms[i];
glm::vec4 transformed_position = transform * glm::vec4(0.0, 1.0, 1.0, 1.0);
vertices[i * 4] = {glm::vec2(transformed_position.x,
transformed_position.y),
glm::vec2(0.0, 1.0),
glm::vec4(1.0, 1.0, 1.0, 1.0)};
transformed_position = transform * glm::vec4(0.0, 0.0, 1.0, 1.0);
vertices[i * 4 + 1] = {glm::vec2(transformed_position.x,
transformed_position.y),
glm::vec2(0.0, 0.0),
glm::vec4(1.0, 1.0, 1.0, 1.0)};
transformed_position = transform * glm::vec4(1.0, 0.0, 1.0, 1.0);
vertices[i * 4 + 2] = {glm::vec2(transformed_position.x,
transformed_position.y),
glm::vec2(1.0, 0.0),
glm::vec4(1.0, 1.0, 1.0, 1.0)};
transformed_position = transform * glm::vec4(1.0, 1.0, 1.0, 1.0);
vertices[i * 4 + 3] = {glm::vec2(transformed_position.x,
transformed_position.y),
glm::vec2(1.0, 1.0),
glm::vec4(1.0, 1.0, 1.0, 1.0)};
}
vertex_buffer->add_data(vertices.data(),
sizeof(SpriteVertex) * (transforms.size() * 4),
GL_DYNAMIC_DRAW);
shader->set_uniform_mat4f("u_view", view);
shader->set_uniform_1i("u_texture", 0);
resource_manager->texture_store.get(texture)->bind();
glDrawElements(GL_TRIANGLES, transforms.size() * 6, GL_UNSIGNED_INT, 0);
}
I have been learning modern OpenGL and in the tutorial I am following I am on framebuffers. There are many examples in the tutorial. So I can call the other buffers later I am putting all the individual buffers in their own functions. My problem though is anything that uses Kernel Effects doesn't work properly when placed in a function.
This is my fragment shader when I place my code in a function:
#version 330 core
in vec2 TexCoords;
out vec4 color;
uniform sampler2D screenTexture;
void EdgeDetection();
const float offset = 1.0 / 300;
void main()
{
EdgeDetection();
}
void EdgeDetection()
{
vec2 offsets[9] = vec2[](
vec2(-offset, offset), // top-left
vec2(0.0f, offset), // top-center
vec2(offset, offset), // top-right
vec2(-offset, 0.0f), // center-left
vec2(0.0f, 0.0f), // center-center
vec2(offset, 0.0f), // center-right
vec2(-offset, -offset), // bottom-left
vec2(0.0f, -offset), // bottom-center
vec2(offset, -offset) // bottom-right
);
float kernel[9] = float[](
1.0, 1.0, 1.0,
1.0, -8.0, 1.0,
1.0, 1.0, 1.0
);
vec3 sample[9];
for(int i = 0; i < 9; i++)
{
sample[i] = vec3(texture(screenTexture, TexCoords.st + offsets[i]));
}
//col = colour
vec3 col = vec3(0.0);
for(int i = 0; i < 9; i++)
col += sample[i] * kernel[i];
color = vec4(col, 1.0);
}
This is when the frag code is in main:
#version 330 core
in vec2 TexCoords;
out vec4 color;
uniform sampler2D screenTexture;
const float offset = 1.0 / 300;
void main()
{
vec2 offsets[9] = vec2[](
vec2(-offset, offset), // top-left
vec2(0.0f, offset), // top-center
vec2(offset, offset), // top-right
vec2(-offset, 0.0f), // center-left
vec2(0.0f, 0.0f), // center-center
vec2(offset, 0.0f), // center-right
vec2(-offset, -offset), // bottom-left
vec2(0.0f, -offset), // bottom-center
vec2(offset, -offset) // bottom-right
);
float kernel[9] = float[](
1.0, 1.0, 1.0,
1.0, -8.0, 1.0,
1.0, 1.0, 1.0
);
vec3 sample[9];
for(int i = 0; i < 9; i++)
{
sample[i] = vec3(texture(screenTexture, TexCoords.st + offsets[i]));
}
//col = colour
vec3 col = vec3(0.0);
for(int i = 0; i < 9; i++)
col += sample[i] * kernel[i];
color = vec4(col, 1.0);
}
When I put the code in main it works just fine. Any idea why it this is happening? I have included a pic of what happens when I run the program.
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;
}
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;
}