I have successfully set up a shader and a test triangle for OpenGL. And I want to set up a transformation uniform that can be applied in the vertex shader. Problem is, I can't see my object anymore after I multiply my vec4 position with the mat4 transform. Where am I doing something wrong?
Vertex shader:
#version 120
attribute vec3 vertices;
attribute vec3 colors;
attribute vec2 texCoords;
uniform mat4 transform;
varying vec3 shared_colors;
varying vec2 shared_texCoords;
void main() {
gl_Position = transform * vec4(vertices, 1.0);
//Send data to fragment shader
shared_colors = colors;
shared_texCoords = texCoords;
}
Fragment shader:
#version 120
uniform sampler2D diffuse;
varying vec3 shared_colors;
varying vec2 shared_texCoords;
void main() {
gl_FragColor = vec4(shared_colors, 1);
//gl_FragColor = texture2D(diffuse, shared_texCoords); //vec4(1, 0, 0, 1);
}
Shader class:
#include "Shader.h"
Shader::Shader(string fileName) {
m_program = glCreateProgram();
m_shaders[SHA_VERTEX] = createShader(loadShader(fileName + ".vs"), GL_VERTEX_SHADER);
m_shaders[SHA_FRAGMENT] = createShader(loadShader(fileName + ".fs"), GL_FRAGMENT_SHADER);
for (int i = 0; i < SHA_COUNT; i++) {
glAttachShader(m_program, m_shaders[i]);
}
glBindAttribLocation(m_program, VBO_VERTEX, "vertices");
glBindAttribLocation(m_program, VBO_COLOR, "colors");
glBindAttribLocation(m_program, VBO_TEXCORD, "texCoords");
glLinkProgram(m_program);
checkShaderError(m_program, GL_LINK_STATUS, true, "Error linking shader program");
glValidateProgram(m_program);
checkShaderError(m_program, GL_VALIDATE_STATUS, true, "Invalid shader program");
m_uniforms[UNI_TRANSFORM] = glGetUniformLocation(m_program, "transform");
}
Shader::~Shader() {
for (int i = 0; i < SHA_COUNT; i++) {
glDetachShader(m_program, m_shaders[i]);
glDeleteShader(m_shaders[i]);
}
glDeleteProgram(m_program);
}
string Shader::loadShader(string filePath) {
ifstream file;
file.open((filePath).c_str());
string output;
string line;
if(file.is_open()) {
while(file.good()) {
getline(file, line);
output.append(line + "\n");
}
}
else {
printf("Unable to load shader: %s\n", filePath.c_str());
}
return output;
}
void Shader::checkShaderError(GLuint shader, GLuint flag, bool isProgram, string errorMessage) {
GLint success = 0;
GLchar error[1024] = {0};
if (isProgram) {
glGetProgramiv(shader, flag, &success);
}
else {
glGetShaderiv(shader, flag, &success);
}
if (success == GL_FALSE) {
if(isProgram) {
glGetProgramInfoLog(shader, sizeof(error), NULL, error);
}
else {
glGetShaderInfoLog(shader, sizeof(error), NULL, error);
}
printf("%s: '%s'\n", errorMessage.c_str(), error);
}
}
GLuint Shader::createShader(string text, unsigned int type) {
GLuint shader = glCreateShader(type);
if (shader == 0) {
printf("Error compiling shader type %i\n", type);
}
const GLchar *p[1];
p[0] = text.c_str();
GLint lengths[1];
lengths[0] = text.length();
glShaderSource(shader, 1, p, lengths);
glCompileShader(shader);
checkShaderError(shader, GL_COMPILE_STATUS, false, "Error compiling shader!");
return shader;
}
void Shader::update(Transform *matrix) {
glm::mat4 model = matrix->getModel();
glUniformMatrix4fv(m_uniforms[UNI_TRANSFORM], 1, GL_FALSE, &model[0][0]);
}
void Shader::enable(bool state) {
if (state) {
glUseProgram(m_program);
}
else {
glUseProgram(NULL);
}
}
Mesh class (or, my object class if you rather call it that):
#include "Mesh.h"
Mesh::Mesh() {
initMesh();
}
Mesh::Mesh(ObjectData *obj) {
initMesh();
//Set object to parameter
object = obj;
initVBO();
}
Mesh::~Mesh() {
delete transform;
//Delete buffer
glDeleteBuffers(VBO_COUNT, buffers);
//Delete array
glDeleteVertexArrays(1, &arrayObject);
}
void Mesh::draw() {
if (initialized) {
shader->update(transform);
shader->enable(true);
texture->enable(true);
//Tell OpenGL which array to use
glBindVertexArray(arrayObject);
glDrawArrays(GL_TRIANGLES, 0, object->vertices.size());
glBindVertexArray(NULL);
shader->enable(false);
texture->enable(false);
}
}
void Mesh::initMesh() {
initialized = false;
shader = new Shader(DIR_SHADERS + "BasicShader");
transform = new Transform();
}
void Mesh::initVBO() {
glGenVertexArrays(1, &arrayObject);
//Tell OpenGL which vertex array to use from now
glBindVertexArray(arrayObject);
glGenBuffers(VBO_COUNT, buffers);
//Set buffer data
glBindBuffer(GL_ARRAY_BUFFER, buffers[VBO_VERTEX]);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * object->vertices.size(), &object->vertices.front(), GL_STATIC_DRAW);
//Set shader attribute data
glEnableVertexAttribArray(VBO_VERTEX);
glVertexAttribPointer(VBO_VERTEX, 3, GL_FLOAT, GL_FALSE, NULL, NULL);
//Set buffer data
glBindBuffer(GL_ARRAY_BUFFER, buffers[VBO_COLOR]);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * object->colors.size(), &object->colors.front(), GL_STATIC_DRAW);
//Set shader attribute data
glEnableVertexAttribArray(VBO_COLOR);
glVertexAttribPointer(VBO_COLOR, 3, GL_FLOAT, GL_FALSE, NULL, NULL);
if (object->texCoords.size()) {
//Set buffer data
glBindBuffer(GL_ARRAY_BUFFER, buffers[VBO_TEXCORD]);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2) * object->texCoords.size(), &object->texCoords.front(), GL_STATIC_DRAW);
//Set shader attribute data
glEnableVertexAttribArray(VBO_TEXCORD);
glVertexAttribPointer(VBO_TEXCORD, 2, GL_FLOAT, GL_FALSE, NULL, NULL);
}
//Unbind vertex array
glBindVertexArray(NULL);
initialized = true;
}
void Mesh::updateVBO() {
//Tell OpenGL which vertex array to use from now
glBindVertexArray(arrayObject);
//Set buffer data
glBindBuffer(GL_ARRAY_BUFFER, buffers[VBO_VERTEX]);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * object->vertices.size(), &object->vertices.front(), GL_STATIC_DRAW);
//Set shader attribute data
glEnableVertexAttribArray(VBO_VERTEX);
glVertexAttribPointer(VBO_VERTEX, 3, GL_FLOAT, GL_FALSE, NULL, NULL);
//Set buffer data
glBindBuffer(GL_ARRAY_BUFFER, buffers[VBO_COLOR]);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * object->colors.size(), &object->colors.front(), GL_STATIC_DRAW);
//Set shader attribute data
glEnableVertexAttribArray(VBO_COLOR);
glVertexAttribPointer(VBO_COLOR, 3, GL_FLOAT, GL_FALSE, NULL, NULL);
if (object->texCoords.size()) {
//Set buffer data
glBindBuffer(GL_ARRAY_BUFFER, buffers[VBO_TEXCORD]);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2) * object->texCoords.size(), &object->texCoords.front(), GL_STATIC_DRAW);
//Set shader attribute data
glEnableVertexAttribArray(VBO_TEXCORD);
glVertexAttribPointer(VBO_TEXCORD, 2, GL_FLOAT, GL_FALSE, NULL, NULL);
}
//Unbind vertex array
glBindVertexArray(NULL);
}
void Mesh::setShader(string file) {
shader = new Shader(file);
}
void Mesh::setTexture(string file) {
texture = new Texture(file);
}
void Mesh::loadObject(string file) {
//Example object
object = new ObjectData();
object->vertices.push_back(glm::vec3(-0.5, -0.5, 0));
object->vertices.push_back(glm::vec3(0, 0.5, 0));
object->vertices.push_back(glm::vec3(0.5, -0.5, 0));
//object->texCoords.push_back(glm::vec2(0, 0));
//object->texCoords.push_back(glm::vec2(0.5, 1));
//object->texCoords.push_back(glm::vec2(1, 0));
object->colors.push_back(glm::vec3(255, 0, 0));
object->colors.push_back(glm::vec3(255, 0, 0));
object->colors.push_back(glm::vec3(255, 0, 0));
//object->vertices.push_back(glm::vec3(0.5, 0.5, 0));
//object->vertices.push_back(glm::vec3(0.75, 1, 0));
//object->vertices.push_back(glm::vec3(1, 0.5, 0));
//object->texCoords.push_back(glm::vec2(0, 0));
//object->texCoords.push_back(glm::vec2(0.5, 1));
//object->texCoords.push_back(glm::vec2(1, 0));
//object->colors.push_back(glm::vec3(0, 255, 0));
//object->colors.push_back(glm::vec3(0, 255, 0));
//object->colors.push_back(glm::vec3(0, 255, 0));
if (initialized) {
updateVBO();
}
else {
initVBO();
}
}
Transform class:
#include "Transform.h"
Transform::Transform() {
position = glm::vec3();
rotation = glm::vec3();
scale = glm::vec3(1, 1, 1);
}
Transform::~Transform() {
}
void Transform::setPosition(glm::vec3 pos) {
position = pos;
}
void Transform::setRotation(glm::vec3 rot) {
rotation = rot;
}
void Transform::setScale(glm::vec3 sca) {
scale = sca;
}
glm::vec3 Transform::getPosition() {
return position;
}
glm::vec3 Transform::getRotation() {
return rotation;
}
glm::vec3 Transform::getScale() {
return scale;
}
glm::mat4 Transform::getModel() {
glm::mat4 pos = glm::translate(position);
glm::mat4 rotX = glm::rotate(rotation.x, glm::vec3(1, 0, 0));
glm::mat4 rotY = glm::rotate(rotation.y, glm::vec3(0, 1, 0));
glm::mat4 rotZ = glm::rotate(rotation.z, glm::vec3(0, 0, 1));
glm::mat4 sca = glm::scale(scale);
glm::mat4 rot = rotZ * rotY * rotX;
glm::mat4 finalMatrix = pos * rot * sca;
return finalMatrix;
}
From your code:
void Mesh::draw() {
if (initialized) {
shader->update(transform);
shader->enable(true);
GL uniforms are per program state, and setting a uniform will affect the currently bound program object. Since you do not have the program object bound at the time you try to set the uniform, the uniform is left at its default state (all zeros). Just switch these two lines...
Related
I'm trying to build a voxel engine, and to do this I have to create hundreds of thousands of voxels, and I was hoping I could use instanced rendering. However, the drawing is very unexpected. I'm primarily following the LearnOpenGL guide.
When rendering each voxel individually, the program works fine:
However, when using instanced rendering...
Another angle...
I'm trying to render the voxels in a big chunk, so this is what my code looks like:
voxel.hpp
#pragma once
#include <stdio.h>
#include <iostream>
#include <vector>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using std::vector;
using glm::mat4;
using glm::vec3;
class Voxel {
float radius;
bool visible;
vec3 centerPoint;
public:
unsigned int VBO, VAO, EBO;
Voxel(vec3 center, float size, bool vis = false, bool single = false);
void setMVP(mat4 mvp);
void setVisible(bool v);
void generateElement();
};
voxel.cpp
#include "voxel.hpp"
Voxel::Voxel(vec3 center, float size, bool vis, bool single) {
visible = vis;
centerPoint = center;
radius = size;
generateElement();
}
void Voxel::setVisible(bool v) {
visible = v;
}
void Voxel::generateElement() {
// this time we need all 8 vertices and a length 36 index array
vec3 maxV(centerPoint.x + radius, centerPoint.y + radius, centerPoint.z + radius);
vec3 minV(centerPoint.x - radius, centerPoint.y - radius, centerPoint.z - radius);
float vertices[24] = {
maxV.x, maxV.y, maxV.z,
maxV.x, maxV.y, minV.z,
maxV.x, minV.y, minV.z,
maxV.x, minV.y, maxV.z,
minV.x, minV.y, maxV.z,
minV.x, maxV.y, maxV.z,
minV.x, maxV.y, minV.z,
minV.x, minV.y, minV.z,
};
unsigned int indices[36] = {
0, 2, 1, // maxV.x
0, 2, 3,
2, 6, 1, // minV.z
2, 6, 7,
2, 4, 3, // minV.y
2, 4, 7,
4, 6, 5, // minV.x
4, 6, 7,
1, 5, 0, // maxV.y
1, 5, 6,
0, 4, 3, // maxV.z
0, 4, 5,
};
// for individual rendering there would be shader code here
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
// load data into vertex buffers
glBindBuffer(GL_ARRAY_BUFFER, VBO);
// glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices[0], GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
// glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), &indices[0], GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
// // set the vertex attribute pointers
// // vertex Positions
glEnableVertexAttribArray(0);
// glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vec3), (void*)0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
// glBindVertexArray(VAO);
// set attribute pointers for matrix (4 times vec4)
glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)0);
glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(glm::vec4)));
glEnableVertexAttribArray(5);
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(glm::vec4) * 2));
glEnableVertexAttribArray(6);
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (void*)(sizeof(glm::vec4) * 3));
glVertexAttribDivisor(3, 1);
glVertexAttribDivisor(4, 1);
glVertexAttribDivisor(5, 1);
glVertexAttribDivisor(6, 1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
chunk.hpp
#pragma once
#include <stdio.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include "voxel.hpp"
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using std::vector;
using glm::mat4;
using glm::vec3;
class Chunk {
vec3 centerPoint;
int voxelNum;
int shaderProgram;
unsigned int VBO, EBO, VAO;
mat4 VP;
public:
Chunk(vec3 center, float radius, int rinv);
void setVP(mat4 vp);
void setVisible(bool v);
void draw();
};
chunk.cpp
#include "chunk.hpp"
#include <iostream>
#include <vector>
#include <algorithm>
#include <stdlib.h>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using std::vector;
using glm::mat4;
using glm::vec3;
Chunk::Chunk(vec3 centerPoint, float radius, int rinv) {
vec3 endPoint(centerPoint.x - radius, centerPoint.y - radius, centerPoint.z - radius);
float distVox = 2 * radius/rinv;
voxelNum = pow(rinv, 3);
mat4* modelMatrices = new mat4[voxelNum];
srand(glfwGetTime()); // initialize random seed
for (int z = 0; z < rinv; z++) {
for (int y = 0; y < rinv; y++) {
for (int x = 0; x < rinv; x++) {
glm::mat4 model = glm::mat4(1.0f);
model = translate(model, vec3(endPoint.x + (x + 0.5) * distVox, endPoint.y + (y + 0.5) * distVox, endPoint.z + (z + 0.5) * distVox));
model = scale(model, vec3(radius));
int index = x + y * rinv + z * pow(rinv, 2);
modelMatrices[index] = model;
}
}
}
const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 3) in mat4 aInstanceMatrix;\n"
"uniform mat4 VP;\n"
"void main()\n"
"{\n"
" gl_Position = VP * aInstanceMatrix * vec4(aPos, 1.0);\n"
"}\n\0";
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"uniform vec3 color;\n"
"void main()\n"
"{\n"
" FragColor = vec4(color, 1.0f);\n"
"}\n\0";
// vertex shader
int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// check for shader compile errors
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// fragment shader
int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// check for shader compile errors
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// link shaders
shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// check for linking errors
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, voxelNum * sizeof(mat4), &modelMatrices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void Chunk::setVP(mat4 vp) {
VP = vp;
}
void Chunk::draw() {
glUseProgram(shaderProgram);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram, "VP"), 1, GL_FALSE, &VP[0][0]);
Voxel eVox(vec3(0.0f), 1.0f, true, false);
glBindVertexArray(eVox.VAO);
glDrawElementsInstanced(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0, voxelNum);
glBindVertexArray(0);
}
main.cpp
#include <iostream>
using namespace std;
#include "chunk.hpp"
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;
//Global Variables
GLFWwindow* window;
const char* SCR_TITLE = "WORKINGPLANET";
const int SCR_WIDTH = 500, SCR_HEIGHT = 500;
float x_rot = 0.0f;
float y_rot = 0.0f;
float y_rot_clamp = 89.999f;
// timing
float deltaTime = 0.0f; // time between current frame and last frame
float lastFrame = 0.0f;
void mouseCallback(GLFWwindow *window, int button, int action, int mods);
vec3 X_AXIS = vec3(1.0f, 0.0f, 0.0f);
vec3 Y_AXIS = vec3(0.0f, 1.0f, 0.0f);
//Main Program
int main()
{
//Constructor Code
if(!glfwInit())
{
cerr << "Error!!GLFW";
return -1;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
if(!(window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, SCR_TITLE, NULL, NULL)))
{
cerr << "Error!!GLFW window";
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc) glfwGetProcAddress)) {
std::cout << "Failed to initialize OpenGL context" << std::endl;
return -1;
}
Chunk chunk(vec3(0.0f), 0.5, 2);
mat4 view = mat4(1.0);
vec3 cameraPos = glm::vec3(0.0f, 0.0f, 4.0f);
view = lookAt(cameraPos, vec3(0,0,0), vec3(0,1,0));
//Loop Events
while(!glfwWindowShouldClose(window))
{
// per-frame time logic
float currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
// Tweak these values to change the sensitivity
float scale_x = 7.0f / SCR_WIDTH;
float scale_y = 7.0f / SCR_HEIGHT;
float rotSpeed = 350.0f;
float rot = scale_x * rotSpeed;
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
rot = scale_y * rotSpeed;
if (y_rot + rot > y_rot_clamp)
rot = y_rot_clamp - y_rot;
view = rotate(view, (float)radians(rot), X_AXIS);
y_rot += rot;
} if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
rot = scale_y * rotSpeed;
if (y_rot - rot < -y_rot_clamp)
rot = y_rot + y_rot_clamp;
view = rotate(view, (float)radians(-rot), X_AXIS);
y_rot -= rot;
} if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
view = rotate(view, (float)radians(-rot), Y_AXIS);
x_rot -= rot;
} if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
view = rotate(view, (float)radians(rot), Y_AXIS);
x_rot += rot;
} if (glfwGetKey(window, GLFW_KEY_R) == GLFW_PRESS) {
view = lookAt(cameraPos, vec3(0,0,0), vec3(0,1,0));
x_rot = 0.0f;
y_rot = 0.0f;
}
mat4 projection = perspective(radians(45.0f), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
//Rendering
chunk.setVP(projection * view);
chunk.draw();
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
I'm totally stuck. Adding more voxels doesn't change how the instanced bug looks.
Interestingly, commenting out the glLinkProgram(shaderProgram); in chunk.cpp makes this bug entirely different, with the chunk appearing as one huge voxel that emcompasses the entire cube.
Your VBO setup doesn't make the slightest sense. You set up your per-instance transformation matrix to use the same data as your geometry in Voxel::generateElement().
You later upload all your transformation matrixes into a separate VBO, but the attribute pointers still point to the geometry VBO. YOu need to move the attribute setup for the instanced attribute out of Voxel::generateElement() and into Chunk::Chunk() so you can tell it to use that VBO as source for the model matrices.
Hey there Im trying to draw a simple quad with 2 triangles in OpenGL through a vbo.
However I have looked at my code multiple times and I don't see what I am missing.
I ain't no Open GL expert, The code was working fine without any buffers however when I switchted to VBO Im not seeing anything anymore. OpenGL also doesn't provide any helpfull errors.
Image::Image(Graphics * GFX)
{
glm::vec2 corners[2];
corners[0] = glm::vec2(0, 0);
corners[1] = glm::vec2(1, 1);
vertices = new GLfloat[30]
{
//Vertices XYZ TexCoord X,Y
corners[0].x, corners[0].y, 0.0f, 0,0,
corners[0].x, corners[1].y, 0.0f, 0,1,
corners[1].x, corners[0].y, 0.0f, 1,0,
corners[1].x,corners[1].y,0.0f, 1,1,
corners[0].x, corners[1].y,0.0f, 0,1,
corners[1].x, corners[0].y, 0.0f, 1,0
};
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//Setting up some stuff
const char *vertexShaderSource =
"attribute vec4 vPosition; \n"
"attribute vec2 vTexCoord; \n"
"void main() \n"
"{ \n"
" gl_Position = vPosition; \n"
"} \n";
const char *fragmentShaderSource =
"precision mediump float; \n"
"void main() \n"
"{ \n"
" gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); \n"
"} \n";
// Load and compile the vertex/fragment shaders
vertexShader = GFX->LoadShader(GL_VERTEX_SHADER, (const char*)vertexShaderSource);
fragmentShader = GFX->LoadShader(GL_FRAGMENT_SHADER, (const char*)fragmentShaderSource);
// Create the program object
programObject = glCreateProgram();
// now we have the V and F shaders attach them to the progam object
glAttachShader(programObject, vertexShader);
glAttachShader(programObject, fragmentShader);
// Link the program
glLinkProgram(programObject);
// Check the link status
// Link the program
GLint AreTheylinked;
glGetProgramiv(programObject, GL_LINK_STATUS, &AreTheylinked);
if (!AreTheylinked)
{
GLint RetinfoLen = 0;
// check and report any errors
glGetProgramiv(programObject, GL_INFO_LOG_LENGTH, &RetinfoLen);
if (RetinfoLen > 1)
{
GLchar* infoLog = (GLchar*)malloc(sizeof(char) * RetinfoLen);
glGetProgramInfoLog(programObject, RetinfoLen, NULL, infoLog);
fprintf(stderr, "Error linking program:\n%s\n", infoLog);
free(infoLog);
}
glDeleteProgram(programObject);
}
positionLocation = glGetAttribLocation(programObject, "vPosition");
textureCoordLocation = glGetAttribLocation(programObject, "vTexCoord");
if (glGetError() == GL_NO_ERROR) {}
else
printf("Init failed!\n");
//End setting up
}
Image::~Image()
{
}
void Image::Draw()
{
std::cout << "Calling Draw on Image" << std::endl;
glUseProgram(programObject);
glEnable(GL_DEPTH_TEST);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
GLsizei stride = (5) * sizeof(GLfloat);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, 0);
glEnableVertexAttribArray(0);
glDrawArrays(GL_TRIANGLES, 0, 6);
if (glGetError() != GL_NO_ERROR)
{
printf("UI Draw error\n");
}
glDisableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
And how I am loading the shaders:
GLuint Graphics::LoadShader(GLenum type, const char *shaderSrc)
{
// 1st create the shader object
GLuint TheShader = glCreateShader(type);
if (TheShader == 0) return FALSE; // can't allocate so stop.
// pass the shader source then compile it
glShaderSource(TheShader, 1, &shaderSrc, NULL);
glCompileShader(TheShader);
GLint IsItCompiled;
// After the compile we need to check the status and report any errors
glGetShaderiv(TheShader, GL_COMPILE_STATUS, &IsItCompiled);
if (!IsItCompiled)
{
GLint RetinfoLen = 0;
glGetShaderiv(TheShader, GL_INFO_LOG_LENGTH, &RetinfoLen);
if (RetinfoLen > 1)
{ // standard output for errors
char* infoLog = (char*)malloc(sizeof(char) * RetinfoLen);
glGetShaderInfoLog(TheShader, RetinfoLen, NULL, infoLog);
fprintf(stderr, "Error compiling this shader:\n%s\n", infoLog);
free(infoLog);
}
glDeleteShader(TheShader);
return FALSE;
}
return TheShader;
}
It worked fine without a buffer previously, and saw a white square by using:
glVertexAttribPointer(0, 6, GL_FLOAT, GL_FALSE, 0, vertices);
But now I want to add texture coordinates to my quad through a VBO but nothing shows anymore.
Smoothy101
Your buffer creation looks fine - the problem is your attribute pointer setup. You've added texture coordinates which has changed data layout for each vertex, but you've not handled that in your code.
You need something like this:
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, stride, 0);
glVertexAttribPointer(textureCoordLocation, 2, GL_FLOAT, GL_FALSE, stride, 8);
... not this:
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, 0);
I'm creating a 3D Maze Game and trying to draw a HUD. I'm using openGL, GLSL, and C++.
Im drawing the maze, switching to an orthographic projection, and then drawing the HUD (currently a test triangle). The world rendering works correctly, but the HUD isn't rendering anything.
I'm misunderstanding something conceptually and am not sure where to look for my error(s).
My HUD uses a 2D camera class:
class Camera2D
{
public:
Camera2D();
~Camera2D();
void init(int screenWidth, int screenHeight);
void update();
void draw();
void setPosition(glm::vec2& newPosition){ _position = newPosition; _needsMatrixUpdate = true; };
glm::mat4 getCameraMatrix() { return _cameraMatrix; };
private:
GLuint _vbo;
GLuint _vao;
int _screenWidth, _screenHeight;
bool _needsMatrixUpdate;
glm::vec2 _position;
glm::mat4 _cameraMatrix;
glm::mat4 _orthoMatrix;
};
where the function implementation is
void Camera2D::init(int screenWidth, int screenHeight)
{
_screenWidth = screenWidth;
_screenHeight = screenHeight;
_orthoMatrix = glm::ortho(0.0f, (float)_screenWidth, 0.0f, (float)_screenHeight);
}
void Camera2D::update()
{
if (_needsMatrixUpdate)
{
//Camera Translation
glm::vec3 translate(-_position.x + _screenWidth / 2, -_position.y + _screenHeight / 2, 0.0f);
_cameraMatrix = glm::translate(_orthoMatrix, translate);
_needsMatrixUpdate = false;
}
}
void Camera2D::draw()
{
float _points[] = { 0, 0, 0, 0, 5, 0, 5, 0, 0 };
float _colors[] = { 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1 };
if (_vbo == 0)
{
glGenBuffers(1, &_vbo);
}
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(_points) + sizeof(_colors), nullptr, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(_points), _points);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(_points), sizeof(_colors), _colors);
if (_vao == 0)
{
glGenVertexArrays(1, &_vao);
}
glBindVertexArray(_vao);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(_points)));
glDrawArrays(GL_TRIANGLES, 0, 9);
}
In MainGame.cpp I initialize the HUD and set it's position.
void MainGame::initSystems()
{
GameEngine3D::init();
_window.create("Maze Runner", _screenWidth, _screenHeight);
glEnable(GL_CULL_FACE);
glFrontFace(GL_CCW);
glCullFace(GL_BACK);
initShaders();
//Trap mouse within window
//If SDL_SetRelativeMouseMode fails exit game
if (SDL_SetRelativeMouseMode(SDL_TRUE))
{
_gameState = GameState::EXIT;
}
_hud.init(_screenWidth, _screenHeight);
_hud.setPosition(glm::vec2(_screenWidth / 2, _screenHeight / 2));
//Generate Maze
mazeAlgor.generateMazeWeights();
mazeAlgor.generateMaze();
mazeAlgor.printMaze();
}
Update it in the game loop
void MainGame::gameLoop()
{
while (_gameState != GameState::EXIT)
{
processInput();
//update the camera model-view-projection matrix
_camera.Update();
_hud.update();
draw();
}
}
And finally draw it"
void MainGame::draw()
{
glClearDepth(1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
_shaderProgram.use();
//locate the location of "MVP" in the shader
GLint mvpLocation = _shaderProgram.getUniformLocation("MVP");
//pass the camera matrix to the shader
glm::mat4 cameraMatrix = _camera.getMVPMatrix();
glUniformMatrix4fv(mvpLocation, 1, GL_FALSE, &(cameraMatrix[0][0]));
mazeAlgor.drawMaze();
glm::mat4 projMatrix = _hud.getCameraMatrix();
glUniformMatrix4fv(mvpLocation, 1, GL_FALSE, &(projMatrix[0][0]));
_hud.draw();
_shaderProgram.unuse();
_window.swapBuffer();
}
My vertex shader is this:
in vec4 vertexPosition;
in vec4 vertexColor;
out vec4 fragmentColor;
uniform mat4 MVP;
void main()
{
gl_Position = MVP * vertexPosition;
fragmentColor = vertexColor;
}
I have a feeling that I'm incorrectly translating in the update() function.
There are two mistakes in your code that could cause the problem:
glm::mat4 projMatrix = _hud.getCameraMatrix();
getCameraMatrix() does not return your projection matrix
glUniformMatrix4fv(mvpLocation, 1, GL_FALSE, &(projMatrix[0][0]));
You're assigning your "projection matrix" to your model view projection matrix (MVP)
The fixed code could look like this:
glm::mat4 modelviewMatrix = _hud.getCameraMatrix(); // _hud._cameraMatrix
glm::mat4 projMatrix = _hud.getProjectionMatrix(); // _hud._orthoMatrix
glm::mat4 mvp = projMatrix * modelviewMatrix;
glUniformMatrix4fv(mvpLocation, 1, GL_FALSE, glm::value_ptr(mvp));
I also recommend you read this and this.
I am trying to implement soft particles in my projects.
Everything is fine , I implement the texture also. But when the mouse is moved to a certain angle,
the particles get distorted. The particle is generated in view space.
So, I would like to know how could I implement the billboard in my project so that every particles seem uniform.Here is my code:
bool CETSmokeRenderer::InitBuffers()
{
size_t vertexSize = 3 * 4 * m_NumVertex * sizeof(float);
size_t colorSize = 4 * 4 * m_NumVertex * sizeof(float);
size_t texCoordSize = 2 * 4 * m_NumVertex * sizeof(float);
if(!vertexBuffer)
{
glDeleteBuffersARB(1, &vertexBuffer);
glDeleteBuffersARB(1, &colorBuffer);
glDeleteBuffersARB(1, &texCoordBuffer);
}
glGenBuffersARB(1, &vertexBuffer);
glGenBuffersARB(1, &colorBuffer);
glGenBuffersARB(1, &texCoordBuffer);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexSize, NULL, GL_STREAM_DRAW_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, colorBuffer);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, colorSize, NULL, GL_STREAM_DRAW_ARB);
// Creates the static texture data
size_t len = 2 * 4 * m_NumVertex;
if(0 > m_NumVertex)
{
return false;
}
else if(0 == m_NumVertex)
{
return true;
}
float *texCoords = new float[len];
{
size_t i = 0;
while(i < len)
{
// u v
texCoords[i++] = 0.0f; texCoords[i++] = 0.0f;
texCoords[i++] = 1.0f; texCoords[i++] = 0.0f;
texCoords[i++] = 1.0f; texCoords[i++] = 1.0f;
texCoords[i++] = 0.0f; texCoords[i++] = 1.0f;
}
}
glBindBufferARB(GL_ARRAY_BUFFER_ARB, texCoordBuffer);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, texCoordSize, (void*)texCoords, GL_STATIC_DRAW_ARB);
delete texCoords;
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
return 0;
}
void CETSmokeRenderer::Draw(Camera &cam, bool useTex)
{
if(useTex)
glBindTexture(GL_TEXTURE_2D, texID);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
mBaseView->SetupViewingTransform();
size_t len = particleStore.size();
std::vector<SimpleSmokeParticle> toDraw;
for(size_t i = 0; i < len; i++)
{
SimpleSmokeParticle sp;
sp.transP = particleStore[i].p;
sp.index = i;
toDraw.push_back(sp);
}
//std::sort(toDraw.begin(), toDraw.end(), ParticleCmp);
#ifdef USE_VBO
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, 3 * 4 * m_NumVertex * sizeof(float), NULL, GL_STREAM_DRAW_ARB);
float *vertexPtr = (float*)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
assert(vertexPtr);
for(size_t i = 0, count = 0; count < len; count++)
{
SmokeParticle &prt = particleStore[ toDraw[count].index ];
Point3f &p = toDraw[count].transP;
float w = prt.w / 0.5f;
float h = prt.h / 1.0f;
vertexPtr[i++] = p.x - w; vertexPtr[i++] = p.y - h; vertexPtr[i++] = p.z;
vertexPtr[i++] = p.x + w; vertexPtr[i++] = p.y - h; vertexPtr[i++] = p.z;
vertexPtr[i++] = p.x + w; vertexPtr[i++] = p.y + h; vertexPtr[i++] = p.z;
vertexPtr[i++] = p.x - w; vertexPtr[i++] = p.y + h; vertexPtr[i++] = p.z;
}
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, colorBuffer);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, 4 * 4 * m_NumVertex * sizeof(float), NULL, GL_STREAM_DRAW_ARB);
float *colorPtr = (float*)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
assert(colorBuffer);
for(size_t i = 0, count = 0; count < len; count++)
{
SmokeParticle &prt = particleStore[ toDraw[count].index ];
// r g b a
colorPtr[i++] = prt.r; colorPtr[i++] = prt.g; colorPtr[i++] = prt.b; colorPtr[i++] = prt.alpha;
colorPtr[i++] = prt.r; colorPtr[i++] = prt.g; colorPtr[i++] = prt.b; colorPtr[i++] = prt.alpha;
colorPtr[i++] = prt.r; colorPtr[i++] = prt.g; colorPtr[i++] = prt.b; colorPtr[i++] = prt.alpha;
colorPtr[i++] = prt.r; colorPtr[i++] = prt.g; colorPtr[i++] = prt.b; colorPtr[i++] = prt.alpha;
}
glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
// Draws buffered data
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vertexBuffer);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, 0);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, colorBuffer);
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(4, GL_FLOAT, 0, 0);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, texCoordBuffer);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glDrawArrays(GL_QUADS, 0, (GLsizei)len *4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
#else
{..}
glPopMatrix();
}
void CETSmokeRenderer::Render()
{
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Renders depth information
if(useSoftParticles)
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, GL_FALSE);
glClampColorARB(GL_CLAMP_FRAGMENT_COLOR_ARB, GL_FALSE);
glClampColorARB(GL_CLAMP_READ_COLOR_ARB, GL_FALSE);
glClearColor(FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX);
glClear(GL_COLOR_BUFFER_BIT);;
glUseProgramObjectARB(0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, GL_TRUE);
glClampColorARB(GL_CLAMP_FRAGMENT_COLOR_ARB, GL_TRUE);
glClampColorARB(GL_CLAMP_READ_COLOR_ARB, GL_TRUE);
glBindTexture(GL_TEXTURE_2D, 0);
// renders the soft particles
glUseProgramObjectARB(particleShader);
// Sets texture data
GLint texloc = glGetUniformLocationARB(particleShader, "tex");
GLint depthTexloc = glGetUniformLocationARB(particleShader, "depthInfo");
GLint powerloc = glGetUniformLocationARB(particleShader, "power");
glUniform1fARB(powerloc, (float)softParticlePower);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, TextureID());
glUniform1iARB(texloc, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, depthTex);
glUniform1iARB(depthTexloc, 1);
Draw(m_pCamera, false);
// Unbinds shader and textures
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgramObjectARB(0);
}
else
{
glUseProgramObjectARB(particleShader);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, TextureID());
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, depthTex);
Draw(m_pCamera, true);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
glUseProgramObjectARB(0);
}
}
One way of achieving what you are looking for is to utilise point sprites, I have attached some code below that illustrates this in a simple way, hope this helps:
main.cpp
/*
Simple point-sprite particle demo - renders particles using spheres
Requirements:
GLM maths library
Freeglut
*/
#include <gl/glew.h>
#include <gl/freeglut.h>
#include <iostream>
#include "GLSLShader.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_projection.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <cassert>
#define GL_CHECK_ERRORS assert(glGetError()== GL_NO_ERROR)
using namespace std;
class Screen
{
public:
int width, height;
string title;
unsigned int displayFlags, contextFlags;
Screen(string ititle, int iwidth = 1024, int iheight = 768){
Screen(ititle, (GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA), (GLUT_CORE_PROFILE | GLUT_DEBUG), iwidth, iheight)
}
Screen(string ititle, unsigned int disFlags, unsigned int contFlags, int iwidth = 1024, int iheight = 768){
title = ititle; width = iwidth; height = iheight;
displayFlags = disFlags;
contextFlags = contFlags;
}
};
const int TOTAL= 9;
GLfloat positions[3*TOTAL]={-1,0,-1, 0,0,-1, 1,0,-1,-1,0, 0, 0,0, 0, 1,0, 0,-1,0, 1, 0,0, 1, 1,0,1};
GLuint vboID, vaoID;
GLsizei stride = sizeof(GLfloat)*3;
GLSLShader shader;
int filling=1;
// Absolute rotation values (0-359 degrees) and rotiation increments for each frame
float rotation_x=0, rotation_x_increment=0.1f;
float rotation_y=0, rotation_y_increment=0.05f;
float rotation_z=0, rotation_z_increment=0.03f;
glm::mat4 P; //projection matrix;
bool bRotate=true;
void InitShaders(void)
{
shader.LoadFromFile(GL_VERTEX_SHADER, "shader.vert");
shader.LoadFromFile(GL_FRAGMENT_SHADER, "shader.frag");
shader.CreateAndLinkProgram();
shader.Use();
shader.AddAttribute("vVertex");
shader.AddUniform("Color");
shader.AddUniform("lightDir");
shader.AddUniform("MVP");
glUniform3f(shader("lightDir"), 0,0,1);
glUniform3f(shader("Color"),1,0,0);
shader.UnUse();
GL_CHECK_ERRORS;
}
void InitVAO() {
GL_CHECK_ERRORS;
//Create vao and vbo stuff
glGenVertexArrays(1, &vaoID);
glGenBuffers (1, &vboID);
GL_CHECK_ERRORS;
glBindVertexArray(vaoID);
glBindBuffer (GL_ARRAY_BUFFER, vboID);
glBufferData (GL_ARRAY_BUFFER, sizeof(positions), &positions[0], GL_STATIC_DRAW);
GL_CHECK_ERRORS;
glEnableVertexAttribArray(shader["vVertex"]);
glVertexAttribPointer (shader["vVertex"], 3, GL_FLOAT, GL_FALSE,stride,0);
glBindVertexArray(0);
GL_CHECK_ERRORS;
}
void SetupGLBase() {
glGetError();
GL_CHECK_ERRORS;
glClearColor(0.0f,0.0f,0.2f,0.0f);
GL_CHECK_ERRORS;
InitShaders();
InitVAO();
glEnable(GL_DEPTH_TEST); // We enable the depth test (also called z buffer)
GL_CHECK_ERRORS;
glPointSize(50);
}
void OnRender() {
GL_CHECK_ERRORS;
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
//setup matrices
glm::mat4 T = glm::translate(glm::mat4(1.0f),glm::vec3(0.0f, 0.0f, -5));
glm::mat4 Rx = glm::rotate(T, rotation_x, glm::vec3(1.0f, 0.0f, 0.0f));
glm::mat4 Ry = glm::rotate(Rx, rotation_y, glm::vec3(0.0f, 1.0f, 0.0f));
glm::mat4 MV = glm::rotate(Ry, rotation_z, glm::vec3(0.0f, 0.0f, 1.0f));
glm::mat4 MVP = P*MV;
//draw the points
shader.Use();
glUniformMatrix4fv(shader("MVP"), 1, GL_FALSE, glm::value_ptr(MVP));
glBindVertexArray(vaoID);
glDrawArrays(GL_POINTS, 0, TOTAL);
glBindVertexArray(0);
shader.UnUse();
glutSwapBuffers();
}
void OnResize(int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
//setup the projection matrix
P = glm::perspective(45.0f, (GLfloat)w/h, 1.f, 1000.f);
}
void OnShutdown() {
glDeleteBuffers(1, &vboID);
glDeleteVertexArrays(1, &vaoID);
}
void OnKey(unsigned char key, int x, int y)
{
switch (key)
{
case ' ': bRotate=!bRotate; break;
case 'r': case 'R':
if (filling==0)
{
glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); // Filled Polygon Mode
filling=1;
}
else
{
glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); // Outline Polygon Mode
filling=0;
}
break;
}
}
void OnSpecialKey(int key, int x, int y)
{
switch (key)
{
case GLUT_KEY_UP: rotation_x_increment = rotation_x_increment +0.005f; break;
case GLUT_KEY_DOWN: rotation_x_increment = rotation_x_increment -0.005f; break;
case GLUT_KEY_LEFT: rotation_y_increment = rotation_y_increment +0.005f; break;
case GLUT_KEY_RIGHT: rotation_y_increment = rotation_y_increment -0.005f; break;
}
}
void OnIdle() {
if(bRotate) {
rotation_x = rotation_x + rotation_x_increment;
rotation_y = rotation_y + rotation_y_increment;
rotation_z = rotation_z + rotation_z_increment;
}
if (rotation_x > 359) rotation_x = 0;
if (rotation_y > 359) rotation_y = 0;
if (rotation_z > 359) rotation_z = 0;
glutPostRedisplay();
}
void glTestAndInfo(GLEnum glewInitResponse)
{
if (GLEW_OK != glewInitResponse) {
cerr<<"Error: "<<glewGetErrorString(glewInitResponse)<<endl;
} else {
if (GLEW_VERSION_3_3)
{
cout<<"Driver supports OpenGL 3.3 or greater.\nDetails:"<<endl;
}
}
cout<<"Using GLEW "<<glewGetString(GLEW_VERSION)<<endl;
cout<<"Vendor: "<<glGetString (GL_VENDOR)<<endl;
cout<<"Renderer: "<<glGetString (GL_RENDERER)<<endl;
cout<<"Version: "<<glGetString (GL_VERSION)<<endl;
cout<<"GLSL: "<<glGetString (GL_SHADING_LANGUAGE_VERSION)<<endl;
}
void main(int argc, char** argv) {
Screen *screen = news Screen("Point sprites as spheres in OpenGL 3.3");
atexit(OnShutdown);
glutInit(&argc, argv);
glutInitDisplayMode(screen->displayFlags);
glutInitContextVersion (3, 3);
glutInitContextFlags (screen->contextFlags);
glutInitWindowSize(screen->width, screen->height);
glutCreateWindow(screen->title);
glewExperimental = GL_TRUE;
glTestAndInfo(glewInit());
SetupGLBase();
glutDisplayFunc(OnRender);
glutReshapeFunc(OnResize);
glutKeyboardFunc(OnKey);
glutSpecialFunc(OnSpecialKey);
glutIdleFunc(OnIdle);
glutMainLoop();
}
GLSLShader.h
#pragma once
#ifndef GLSL_SHADER_H
#define GLSL_SHADER_H
#include <GL/glew.h>
#include <map>
#include <string>
using namespace std;
class GLSLShader
{
public:
GLSLShader(void);
~GLSLShader(void);
void LoadFromString(GLenum whichShader, const string source);
void LoadFromFile(GLenum whichShader, const string filename);
void CreateAndLinkProgram();
void Use();
void UnUse();
void AddAttribute(const string attribute);
void AddUniform(const string uniform);
GLuint operator[](const string attribute);// indexer: returns the location of the named attribute
GLuint operator()(const string uniform);
private:
enum ShaderType {VERTEX_SHADER, FRAGMENT_SHADER, GEOMETRY_SHADER};
GLuint _program;
int _totalShaders;
GLuint _shaders[3];//0 vertexshader, 1 fragmentshader, 2 geometryshader
map<string,GLuint> _attributeList;
map<string,GLuint> _uniformLocationList;
};
#endif
GLSLShader.cpp
/*
Really basic glsl shader class
*/
#include "GLSLShader.h"
#include <iostream>
#include <fstream>
// constructor
GLSLShader::GLSLShader(void)
{
_totalShaders=0;
_shaders[VERTEX_SHADER]=0;
_shaders[FRAGMENT_SHADER]=0;
_shaders[GEOMETRY_SHADER]=0;
_attributeList.clear();
_uniformLocationList.clear();
}
// destructor
GLSLShader::~GLSLShader(void)
{
_attributeList.clear();
_uniformLocationList.clear();
glDeleteProgram(_program);
}
// loader functions
void GLSLShader::LoadFromString(GLenum type, const string source) {
GLuint shader = glCreateShader (type);
const char * ptmp = source.c_str();
glShaderSource (shader, 1, &ptmp, NULL);
//check whether the shader loads fine
GLint status;
glCompileShader (shader);
glGetShaderiv (shader, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE) {
GLint infoLogLength;
glGetShaderiv (shader, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar *infoLog= new GLchar[infoLogLength];
glGetShaderInfoLog (shader, infoLogLength, NULL, infoLog);
cerr<<"Compile log: "<<infoLog<<endl;
delete [] infoLog;
}
_shaders[_totalShaders++]=shader;
}
void GLSLShader::LoadFromFile(GLenum whichShader, const string filename){
ifstream fp;
fp.open(filename.c_str(), ios_base::in);
if(fp) {
string line, buffer;
while(getline(fp, line)) {
buffer.append(line);
buffer.append("\r\n");
}
//copy to source
LoadFromString(whichShader, buffer);
} else {
cerr<<"Error loading shader: "<<filename<<endl;
}
}
// utilitarian functions
void GLSLShader::CreateAndLinkProgram() {
_program = glCreateProgram ();
if (_shaders[VERTEX_SHADER] != 0) {
glAttachShader (_program, _shaders[VERTEX_SHADER]);
}
if (_shaders[FRAGMENT_SHADER] != 0) {
glAttachShader (_program, _shaders[FRAGMENT_SHADER]);
}
if (_shaders[GEOMETRY_SHADER] != 0) {
glAttachShader (_program, _shaders[GEOMETRY_SHADER]);
}
//link and check whether the program links fine
GLint status;
glLinkProgram (_program);
glGetProgramiv (_program, GL_LINK_STATUS, &status);
if (status == GL_FALSE) {
GLint infoLogLength;
glGetProgramiv (_program, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar *infoLog= new GLchar[infoLogLength];
glGetProgramInfoLog (_program, infoLogLength, NULL, infoLog);
cerr<<"Link log: "<<infoLog<<endl;
delete [] infoLog;
}
glDeleteShader(_shaders[VERTEX_SHADER]);
glDeleteShader(_shaders[FRAGMENT_SHADER]);
glDeleteShader(_shaders[GEOMETRY_SHADER]);
}
void GLSLShader::Use() {
glUseProgram(_program);
}
void GLSLShader::UnUse() {
glUseProgram(0);
}
void GLSLShader::AddAttribute(const string attribute) {
_attributeList[attribute]= glGetAttribLocation(_program, attribute.c_str());
}
// indexer: returns the location of the named attribute
GLuint GLSLShader::operator [](const string attribute) {
return _attributeList[attribute];
}
void GLSLShader::AddUniform(const string uniform) {
_uniformLocationList[uniform] = glGetUniformLocation(_program, uniform.c_str());
}
GLuint GLSLShader::operator()(const string uniform){
return _uniformLocationList[uniform];
}
This code is pretty old and I have no way to test rendering here (no distinct GFX card) so if there are any issues let me know and I can fix it once at my GFX dev machine.
Addendum:
Shaders may help too (dont know how I forgot them, old age maybe catching up on me!) so here they are:
Vertex shader (shader.vert)
#version 330 // set this to whatever minimum version you want to support
in vec3 vVertex;
uniform mat4 MVP;
void main()
{
gl_Position = MVP*vec4(vVertex,1);
}
Fragment shader (shader.frag)
#version 330
out vec4 vFragColour;
uniform vec3 Colour;
uniform vec3 lightDirection;
void main(void)
{
// calculate normal from texture coordinates
vec3 N;
N.xy = gl_PointCoord* 2.0 - vec2(1.0);
float mag = dot(N.xy, N.xy);
if (mag > 1.0) discard; // kill pixels outside the circle we want
N.z = sqrt(1.0-mag); // this might be expensive depending on your hardware
float diffuse = max(0.0, dot(lightDirection, N)); // calculate lighting
vFragColour = vec4(Colour,1) * diffuse;
}
Addendum 2:
To add the freeglut libraries to your build and resolve LNK 1104 errors simply go to *Project >> Properties >> VC++ Directories* and add the directories where your freeglut includes, source libraries and dlls are stored, for example for lib files go to
Add the folders as follows:
DLL Directories: add to Executable Directories
.h file Directories(include folder): add to Include Directories
.cpp file Directories: add to Source Directories
.lib file Directories: add to Library Directories
Hope this helps:)
I'm using VC++10 + OpenGL + the Assimp Library to consume and then render some 3D models.
The code is rendering the positions correctly, but for some reason the textures are seriously bugged. My texcoords appear to be loading correctly as are the texture files themselves - however I can't help but feel that the issue must be located with the loaded textures themselves.
www.flickr.com/photos/95269725#N02/8685913640/in/photostream
{ i seem to have a lack of rep to post inline images }
********** EDIT1 : ***********
So, I've been using the awesome GDebugger application to debug and interrogate the OpenGL pipeline in realtime. 2 things stand out really :
1. The biggy here is that the loaded texture is meant to look like this ->
http://www.flickr.com/photos/95269725#N02/8688860034/in/photostream
but actually looks like this when loaded into OpenGL memory :
http://www.flickr.com/photos/95269725#N02/8688860042/in/photostream/
2. Not sure if this is still applicable(as discussed in the comments), however the GL_TEXTURE_2D state variable is always FALSE throughout the game loop.
So I'm going to have to play with the texture loading code to see if I can get any traction there and post another update.
A few big relevant code chunks{sorry!} :
* Vertex Shader *
#version 420
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec2 texCoord;
uniform mat4 cameraToClipMatrix;
uniform mat4 modelToCameraMatrix;
out vec2 oTexCoord;
out vec4 oNormal;
void main()
{
oTexCoord = texCoord;
vec4 cameraPos = modelToCameraMatrix * vec4(position,1.0);
gl_Position = cameraToClipMatrix * cameraPos;
oNormal = normalize(vec4(modelToCameraMatrix * vec4(normal,0.0)));
}
* Fragment Shader *
#version 420
in vec4 Normal;
in vec2 TexCoord;
layout (location = 0) out vec4 FragColor;
uniform sampler2D gSampler;
void main()
{
FragColor = texture(gSampler, TexCoord);
//FragColor = vec4(1.1, 0.0, 1.1, 1.0);
}
* GL Init etc *
void GLSystem::init() {
InitializeProgram();
glClearColor(0.75f, 0.75f, 1.0f, 1.0f);
glFrontFace(GL_CCW);
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glDepthFunc(GL_LEQUAL);
glDepthRange(0.0f, 1.0f);
}
void GLSystem::InitializeProgram()
{
std::vector<GLuint> shaderList;
shaderList.push_back(LoadShader(GL_VERTEX_SHADER, "VertShader1.vert"));
shaderList.push_back(LoadShader(GL_FRAGMENT_SHADER, "FragShader1.frag"));
theProgram = CreateProgram(shaderList);
modelToCameraMatrixUnif = glGetUniformLocation(theProgram, "modelToCameraMatrix"); // view matrix
cameraToClipMatrixUnif = glGetUniformLocation(theProgram, "cameraToClipMatrix"); // projection matrix
m_samplerUnif = glGetUniformLocation(theProgram, "gSampler"); // grab the gSampler uniform location reference in the fragment shader
float fzNear = 1.0f; float fzFar = 45.0f;
cameraToClipMatrix[0].x = fFrustumScale;
cameraToClipMatrix[1].y = fFrustumScale;
cameraToClipMatrix[2].z = (fzFar + fzNear) / (fzNear - fzFar);
cameraToClipMatrix[2].w = -1.0f;
cameraToClipMatrix[3].z = (2 * fzFar * fzNear) / (fzNear - fzFar);
glUseProgram(theProgram);
glUniformMatrix4fv(cameraToClipMatrixUnif, 1, GL_FALSE, glm::value_ptr(cameraToClipMatrix));
glUseProgram(0);
}
* Texture Loading *
bool CTexture::Load() {
m_texObj = 0; // init to zero
std::auto_ptr<glimg::ImageSet> pImgSet;
try {
pImgSet.reset( glimg::loaders::stb::LoadFromFile(m_filename) );
m_texObj = glimg::CreateTexture( &(*pImgSet), 0); // generates a texture and returns the related texture id
//glimg::SingleImage image = pImgSet->GetImage(0, 0, 0);
//glimg::Dimensions dims = image.GetDimensions();
//GLuint targetTexType = glimg::GetTextureType( &(*pImgSet), 0); // not using this yet - but potentially might need to base this objects targetType on this interpreted value.
//glimg::OpenGLPixelTransferParams params = GetUploadFormatType(image.GetFormat(), 0);
//glPixelStorei(GL_UNPACK_ALIGNMENT, image.GetFormat().LineAlign());
//glGenTextures(1, &m_texObj);
//glActiveTexture(GL_TEXTURE0);
//glBindTexture(GL_TEXTURE_2D, m_texObj);
//glTexImage2D(m_targetType, 0, glimg::GetInternalFormat(image.GetFormat(), 0), dims.width, dims.height, 0, params.format, params.type, image.GetImageData());
//glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, dims.width, dims.height, 0, GL_RGB, GL_UNSIGNED_BYTE, image.GetImageData() );
/*glTexParameterf(m_targetType, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(m_targetType, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(m_targetType, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(m_targetType, GL_TEXTURE_WRAP_T, GL_REPEAT);*/
}
catch(glimg::loaders::stb::StbLoaderException &e) {
std::cout << "Warning : " << e.what() << " || .Image file loading failed for file : '" << m_filename << std::endl;
return false;
}
glBindTexture(m_targetType, 0); // Bind to default texture
return true;
}
* Mesh Loading *
#include "MeshModel.h"
// ----------------------------------------------------------------------------------------
#include "Texture.h"
#include "GLSystem.h"
#include "Game.h"
// ----------------------------------------------------------------------------------------
#include <assert.h>
// ----------------------------------------------------------------------------------------
MeshItem::MeshItem() {
}
MeshItem::MeshItem(MeshModel& p_meshModel) {
m_pmeshModel = &p_meshModel;
p_delete_object_data = true;
VBO = INVALID_OGL_VALUE;
IBO = INVALID_OGL_VALUE;
NBO = INVALID_OGL_VALUE;
TBO = INVALID_OGL_VALUE;
NumVertices = 0;
NumFaces = 0;
NumIndices = 0;
MaterialIndex = INVALID_MATERIAL;
};
MeshItem::~MeshItem() {
if (VBO != INVALID_OGL_VALUE) {
glDeleteBuffers(1, &VBO);
}
if (IBO != INVALID_OGL_VALUE) {
glDeleteBuffers(1, &IBO);
}
if (NBO != INVALID_OGL_VALUE) {
glDeleteBuffers(1, &NBO);
}
if (TBO != INVALID_OGL_VALUE) {
glDeleteBuffers(1, &TBO);
}
}
void MeshItem::BuildVBO() {
glGenVertexArrays(1, &VAO); /* Generate a vertex array object - container for all vertex attribute arrays */
glBindVertexArray(VAO); /* Bind this VAO as the current Vertex Attribute Array container [ Holds the state for all attributes i.e. not the Vertex and Index data ] */
// Positions
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * NumVertices * 3, &Positions[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); // Positions
// Indices
glGenBuffers(1, &IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * NumFaces * 3, &Indices[0], GL_STATIC_DRAW);
// Normals
glGenBuffers(1, &NBO);
glBindBuffer(GL_ARRAY_BUFFER, NBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * NumVertices * 3, &Normals[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0); // Normals
// TexCoords
glGenBuffers(1, &TBO);
glBindBuffer(GL_ARRAY_BUFFER, TBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * NumVertices * 2, &TexCoords[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, 0); // TexCoords
glBindVertexArray(0); // Unbind the VAO
glBindBuffer(GL_ARRAY_BUFFER,0); // Unbind the vertices array buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); // Unbind the indices array buffer
// Our copy of the data is no longer necessary, it is safe in the graphics card memory
if(p_delete_object_data) {
Positions.erase( Positions.begin(), Positions.end() );
Indices.erase( Indices.begin(), Indices.end() );
Normals.erase( Normals.begin(), Normals.end() );
TexCoords.erase( TexCoords.begin(), TexCoords.end() );
}
}
// ********************* MESHMODEL *********************
MeshModel::MeshModel(GLSystem& p_gls)
: m_pgls(&p_gls)
{
m_texUnit = 0;
m_samplerObj = 0;
}
MeshModel::~MeshModel() {
Clear();
}
GLSystem& MeshModel::getGLSystem() {
return *m_pgls;
}
void MeshModel::Clear() {
//for (unsigned int i = 0 ; i < m_textures.size() ; i++) {
// m_textures[i]);
//}
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
}
bool MeshModel::LoadMesh(const std::string& p_filename) {
Clear(); // Release the previously loaded mesh (if it exists)
bool Ret = false;
Assimp::Importer Importer;
const aiScene* pScene = Importer.ReadFile(p_filename.c_str(), aiProcess_Triangulate | aiProcess_GenSmoothNormals /* | aiProcess_FlipWindingOrder*/ /* | aiProcess_FlipUVs*/ | aiProcess_ValidateDataStructure);
//const aiScene* pScene = aiImportFile(p_filename.c_str(), aiProcessPreset_TargetRealtime_MaxQuality);
if (pScene) {
printf("3D Object File '%s' loaded successfully.\n", p_filename.c_str() );
Ret = InitFromScene(pScene, p_filename);
}
else {
printf("Error parsing '%s': '%s'.\n", p_filename.c_str(), Importer.GetErrorString());
}
return Ret;
}
bool MeshModel::InitFromScene(const aiScene* pScene, const std::string& p_filename) {
//m_meshItems.resize(pScene->mNumMeshes);
m_textures.resize(pScene->mNumMaterials);
InitMaterials(pScene, p_filename); // load materials/textures etc
// Initialize the meshes in the scene one by one
for (unsigned int i = 0 ; i < pScene->mNumMeshes ; i++) {
const aiMesh* paiMesh = pScene->mMeshes[i];
MeshItem mItem(*this);
InitMesh(mItem, paiMesh);
mItem.BuildVBO();
m_meshItems.push_back(mItem);
}
return true;
}
void MeshModel::InitMesh(MeshItem& p_meshItem, const aiMesh* p_paiMesh) {
p_meshItem.MaterialIndex = p_paiMesh->mMaterialIndex;
// Indices
p_meshItem.NumFaces = p_paiMesh->mNumFaces;
p_meshItem.NumIndices = p_meshItem.NumFaces * 3;
p_meshItem.Indices.resize(p_meshItem.NumIndices);
for (unsigned int i = 0 ; i < p_paiMesh->mNumFaces ; ++i) {
const aiFace& face = p_paiMesh->mFaces[i];
assert(face.mNumIndices == 3);
p_meshItem.Indices[i*3+0] = face.mIndices[0];
p_meshItem.Indices[i*3+1] = face.mIndices[1];
p_meshItem.Indices[i*3+2] = face.mIndices[2];
}
p_meshItem.NumVertices = p_paiMesh->mNumVertices;
p_meshItem.Positions.resize(p_meshItem.NumVertices * 3);
p_meshItem.Normals.resize(p_meshItem.NumVertices * 3);
p_meshItem.TexCoords.resize(p_meshItem.NumVertices * 2);
for (unsigned int i = 0 ; i < p_paiMesh->mNumVertices ; ++i) {
// Positions
if( p_paiMesh->HasPositions() ) {
p_meshItem.Positions[i*3+0] = p_paiMesh->mVertices[i].x;
p_meshItem.Positions[i*3+1] = p_paiMesh->mVertices[i].y;
p_meshItem.Positions[i*3+2] = p_paiMesh->mVertices[i].z;
}
// Normals
if( p_paiMesh->HasNormals() ) {
p_meshItem.Normals[i*3+0] = p_paiMesh->mNormals[i].x;
p_meshItem.Normals[i*3+1] = p_paiMesh->mNormals[i].y;
p_meshItem.Normals[i*3+2] = p_paiMesh->mNormals[i].z;
}
// TexCoords
if( p_paiMesh->HasTextureCoords(0) ) {
p_meshItem.TexCoords[i*2+0] = p_paiMesh->mTextureCoords[0][i].x;
p_meshItem.TexCoords[i*2+1] = p_paiMesh->mTextureCoords[0][i].y;
}
}
}
bool MeshModel::InitMaterials(const aiScene* pScene, const std::string& p_filename) {
// Extract the directory part from the file name
std::string::size_type SlashIndex = p_filename.find_last_of("/");
std::string Dir;
if (SlashIndex == std::string::npos) {
Dir = ".";
}
else if (SlashIndex == 0) {
Dir = "/";
}
else {
Dir = p_filename.substr(0, SlashIndex);
}
bool Ret = true;
// Initialize the materials
for (unsigned int i = 0 ; i < pScene->mNumMaterials ; i++) {
const aiMaterial* pMaterial = pScene->mMaterials[i];
m_textures[i] = NULL;
std::string FullPath = "";
if (pMaterial->GetTextureCount(aiTextureType_DIFFUSE) > 0) {
aiString Path;
if (pMaterial->GetTexture(aiTextureType_DIFFUSE, 0, &Path, NULL, NULL, NULL, NULL, NULL) == AI_SUCCESS) {
FullPath = Dir + "/" + Path.data;
m_textures[i] = std::make_shared<CTexture>( GL_TEXTURE_2D, FullPath.c_str() );
if ( !m_textures[i]->Load() ) {
printf("Error loading texture '%s'.\n", FullPath.c_str());
m_textures[i].reset();
m_textures[i] = NULL;
Ret = false;
}
else {
printf("Texture File '%s' loaded successfully\n", FullPath.c_str());
}
}
}
// Load a white texture in case the model does not include its own texture
if (!m_textures[i]) {
m_textures[i] = std::make_shared<CTexture>( GL_TEXTURE_2D, "..//Data/Textures/white.png");
printf("A default Texture File was loaded for '%s'.\n", FullPath.c_str());
Ret = m_textures[i]->Load();
}
}
// Genertate a Sampler object
glGenSamplers(1, &m_samplerObj);
glSamplerParameteri(m_samplerObj, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glSamplerParameteri(m_samplerObj, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glSamplerParameteri(m_samplerObj, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glSamplerParameteri(m_samplerObj, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
return Ret;
}
void MeshModel::DrawMesh() {
for (unsigned int i = 0 ; i < m_meshItems.size() ; i++) {
glUseProgram( getGLSystem().getProgram() ); // Bind to our selected shader program
glBindVertexArray(m_meshItems[i].VAO);
const unsigned int MaterialIndex = m_meshItems[i].MaterialIndex;
// If textures exist then bind them to samplers etc
if (MaterialIndex < m_textures.size() && m_textures[MaterialIndex]) {
glUniform1i(m_pgls->m_samplerUnif, 0);
glActiveTexture(GL_TEXTURE0 + 0);
glBindTexture(GL_TEXTURE_2D, m_textures[MaterialIndex]->m_texObj);
glBindSampler(0, m_samplerObj);
} else {
printf("MeshItem has no material!");
}
// RTS
glutil::MatrixStack currMatrix;
currMatrix.Translate(glm::vec3(0.0f, -3.0f, -10.0f));
currMatrix.Scale(0.1f, 0.1f, 0.1f);
currMatrix.RotateX(-90);
float a = Game::m_tick.asSeconds() /10;
float fAngRad = m_pgls->ComputeAngleRad(a, 2.0);
float fCos = cosf(fAngRad);
float fSin = sinf(fAngRad);
glm::mat3 theMat(1.0f);
theMat[0].x = fCos; theMat[1].x = -fSin;
theMat[0].y = fSin; theMat[1].y = fCos;
currMatrix.ApplyMatrix(glm::mat4(theMat));
glUniformMatrix4fv(m_pgls->modelToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(currMatrix.Top()));
glDrawElements(GL_TRIANGLES, m_meshItems[i].NumIndices, GL_UNSIGNED_INT, 0);
glBindVertexArray(0); // Unbind the VAO
glUseProgram(0); // Close the link to the bound shader programs
}
}
I notice your vertex shader declares:
out vec2 oTexCoord;
but your fragment shader declares:
in vec2 TexCoord;
This might leave your texture coordinates undefined.
I think you need to enable textures with glEnable(GL_TEXTURES_2D) in your init section. I get the same look by commenting out that line from my project. Here's the code, if that helps:
EnableGraphics::EnableGraphics()
{
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glOrtho(-1.0, 1.0, -1.0, 1.0, 0.0, 1.0);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // typical alpha transparency
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
EDIT:
In case your link dies, I should add that your screenshot shows a 3D model with no textures or shading, although it has colors.