I send double precision data to my compute shader using an ssbo but somehow looses precision somewhere in the shader. I posted this problem here but has not yet received a response.
I read a position which contains 4 doubles that I use in calculations. If I in the beginning of the shader write the position to the buffer the values are correct. If I write to the buffer after my calculations I get a precision loss. I never change the values in the position. In my test I can even change "true" to "variable == variable" and loose precision only on that. Some of the code is shown in the post i linked to.
I had a similar problem with my constants which was solved with the LF suffix. Is there a similar fix for variables?
I have tried to isolate the problem, here is my code:
My .csh-file:
#version 430
struct aVec4 {
double x, y, z, w;
};
struct FT {
aVec4 force;
aVec4 torque;
};
struct Triangle {
aVec4 position;
aVec4 normal;
aVec4 depth;
};
layout( std430, binding = 0 ) buffer abc { Triangle bs[]; };
layout( std430, binding = 1 ) buffer def { FT forces[]; };
layout( local_size_x = 1 ) in;
dvec3 toVec3( in aVec4 vector ) {
dvec3 v = dvec3( vector.x, vector.y, vector.z );
return v;
}
aVec4 function1( inout Triangle triangles[2], inout int numTriangles ) {
Triangle anotherTriangle = bs[gl_GlobalInvocationID.x];
int numBelow = 1;
if ( anotherTriangle.depth.x < 0.0LF ) {
numBelow++;
}
if ( numBelow == numBelow ) {
numTriangles = 1;
aVec4 result = anotherTriangle.position;
return result;
}
}
FT function2( in Triangle triangles[2], in int numTriangles ) {
FT ft;
dvec3 force = dvec3( 0.0LF, 0.0LF, 0.0LF );
for ( int i = 0; i < numTriangles; i++ ){
dvec3 normal = toVec3( triangles[i].normal );
force += - normal;
}
ft.force = triangles[0].position;
return ft;
}
void main()
{
Triangle triangles[2];
triangles[0] = bs[gl_GlobalInvocationID.x];
int numTriangles = 1;
aVec4 result = function1( triangles, numTriangles );
FT ft = function2( triangles, numTriangles );
ft.torque = result;
forces[gl_GlobalInvocationID.x] = ft;
}
My .cpp-file:
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <vector>
#include <fstream>
#include <iostream>
#include <iomanip>
#include <string>
#include <cmath>
class Vec3
{
public:
Vec3()
: x(0)
, y(0)
, z(0)
, w(0)
{
}
Vec3(double x, double y, double z)
: x(x)
, y(y)
, z(z)
, w(0)
{
}
double x, y, z, w;
};
std::ostream& operator<<(std::ostream& stream, const Vec3& v)
{
stream << std::setprecision(20) << std::setw(20) << std::scientific;
stream << "Vec3(" <<
std::setw(23) << v.x << ", " <<
std::setw(23) << v.y << ", " <<
std::setw(23) << v.z << ") (" <<
std::setw(23) << v.w << ")";
return stream;
}
GLuint loadShader( std::string fileName )
{
GLuint program = glCreateProgram( );
GLuint shader = glCreateShader( GL_COMPUTE_SHADER );
std::ifstream shaderStream(fileName.c_str(), std::ios::in );
if (!shaderStream.is_open())
{
std::cout << "Could not open shader source file '" << fileName << "'." << std::endl;
exit(1);
}
std::string src;
std::string line = "";
while ( getline( shaderStream, line ) )
src += "\n" + line;
char const* srcPointer = src.c_str( );
glShaderSource( shader, 1, &srcPointer, NULL );
glCompileShader( shader );
int rValue;
glGetShaderiv( shader, GL_COMPILE_STATUS, &rValue );
if (!rValue)
{
std::cout << "Unable to compile compute shader" << std::endl;
GLchar log[ 10240 ];
GLsizei length;
glGetShaderInfoLog( shader, 10239, &length, log );
fprintf( stderr, "Compiler log:\n%s\n", log );
exit( 40 );
}
glAttachShader(program, shader);
glLinkProgram(program);
glGetProgramiv( program, GL_LINK_STATUS, &rValue );
if (!rValue)
{
std::cout << "Unable to link compute shader program" << std::endl;
GLchar log[ 10240 ];
GLsizei length;
glGetProgramInfoLog( program, 10239, &length, log );
fprintf( stderr, "Linker log:\n%s\n", log );
exit( 41 );
}
glDeleteShader( shader );
return program;
}
struct ShaderData
{
Vec3 position;
Vec3 normal;
Vec3 depth;
};
int main( int argc, char **argv ) {
glutInit( &argc, argv );
glutCreateWindow( "TEST1" ); //TODO: Why?
glewInit( );
std::string shaderFileName = "tutorial_computeShaderBugSearch.csh";
GLuint program = loadShader( shaderFileName );
GLuint ssbo;
GLuint result;
glGenBuffers( 1, &ssbo );
glGenBuffers( 1, &result );
glUseProgram( program );
std::vector< ShaderData > buf;
buf.resize( 1 );
ShaderData shaderData;
shaderData.position = Vec3( double(1) / double(3), 0, 0 );
shaderData.normal = Vec3( 1, 1, 1 );
shaderData.depth.x = 1;
buf[ 0 ] = shaderData;
glBindBuffer( GL_SHADER_STORAGE_BUFFER, ssbo );
glBufferData( GL_SHADER_STORAGE_BUFFER, buf.size( ) * sizeof(ShaderData), buf.data( ), GL_STATIC_DRAW );
std::vector< Vec3 > forces;
forces.resize( 2 ); // 1 for the forces + 1 for the torques
glBindBuffer( GL_SHADER_STORAGE_BUFFER, result );
glBufferData( GL_SHADER_STORAGE_BUFFER, forces.size( ) * sizeof(Vec3), forces.data( ), GL_STATIC_DRAW );
glUseProgram( program );
glBindBufferBase( GL_SHADER_STORAGE_BUFFER, 0, ssbo );
glBindBufferBase( GL_SHADER_STORAGE_BUFFER, 1, result );
glDispatchCompute( 1, 1, 1 );
glMemoryBarrier( GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT );
glBindBuffer( GL_SHADER_STORAGE_BUFFER, result );
Vec3* ptr = (Vec3*)glMapBuffer( GL_SHADER_STORAGE_BUFFER, GL_READ_ONLY );
Vec3 a = ptr[ 0 ];
Vec3 b = ptr[ 1 ];
std::cout << "a: " << std::setprecision(20) << a.x << std::endl;
std::cout << "b: " << std::setprecision(20) << b.x << std::endl;
std::cout << "diff: " << std::abs(a.x-b.x) << std::endl;
}
This produces the output:
a: 0.3333333432674408
b: 0.33333333333333331
diff: 9.9341074810688212e-099
Related
I'm having classes of computer graphics on OpenGL. There we study and work with Visual Studio 2015 while I run Linux on my laptop. So there some differences between composing a program in our classes and in lessons I found on Wikibooks. I tried to run one tutorial code from there and everything was fine, while I couldn't run my code I wrote at my lesson.
So I tried manipulating with my and tutorial code. I succeeded a few. The program runs but not shows my figures. So it actually must show a chesstable. But, for my regret, it shows a background color only. What may be wrong with that?
The first part on onDisplay() is not displayed. The commented part is from tutorial which works and shows a triangle.
Full code:
#include <stdio.h>
#include <stdlib.h>
/* Use glew.h instead of gl.h to get all the GL prototypes declared */
#include <GL/glew.h>
/* Using the GLUT library for the base windowing setup */
#include <GL/freeglut.h>
GLuint program;
GLint attribute_coord2d;
int init_resources()
{
GLint compile_ok = GL_FALSE, link_ok = GL_FALSE;
GLuint vs = glCreateShader( GL_VERTEX_SHADER );
const char *vs_source =
#ifdef GL_ES_VERSION_2_0
"#version 100\n" // OpenGL ES 2.0
#else
"#version 120\n" // OpenGL 2.1
#endif
"attribute vec2 coord2d; "
"void main(void) { "
" gl_Position = vec4(coord2d, 0.0, 1.0); "
"}";
glShaderSource( vs, 1, &vs_source, NULL );
glCompileShader( vs );
glGetShaderiv( vs, GL_COMPILE_STATUS, &compile_ok );
if( !compile_ok )
{
fprintf( stderr, "Error in vertex shader\n" );
return 0;
}
GLuint fs = glCreateShader( GL_FRAGMENT_SHADER );
const char *fs_source =
#ifdef GL_ES_VERSION_2_0
"#version 100\n" // OpenGL ES 2.0
#else
"#version 120\n" // OpenGL 2.1
#endif
"void main(void) { "
" gl_FragColor[0] = 0.0; "
" gl_FragColor[1] = 0.0; "
" gl_FragColor[2] = 1.0; "
"}";
glShaderSource( fs, 1, &fs_source, NULL );
glCompileShader( fs );
glGetShaderiv( fs, GL_COMPILE_STATUS, &compile_ok );
if( !compile_ok )
{
fprintf( stderr, "Error in fragment shader\n" );
return 0;
}
program = glCreateProgram();
glAttachShader( program, vs );
glAttachShader( program, fs );
glLinkProgram( program );
glGetProgramiv( program, GL_LINK_STATUS, &link_ok );
if( !link_ok )
{
fprintf( stderr, "glLinkProgram:" );
return 0;
}
const char* attribute_name = "coord2d";
attribute_coord2d = glGetAttribLocation( program, attribute_name );
if( attribute_coord2d == -1 )
{
fprintf( stderr, "Could not bind attribute %s\n", attribute_name );
return 0;
}
return 1;
}
void chess( double x, double y, double w, double h, int k )
{
glColor3f( 0.6, 0.6, 0.6 );
glRecti( 20, 20, 480, 480 );
for( int i = 0; i < 8; i++ )
{
glRasterPos2i( ( i + 1 )*x + 20, 30 );
glutBitmapCharacter( GLUT_BITMAP_9_BY_15, 'A' + i );
}
for( int j = 0; j < 8; j++ )
{
for( int i = 0; i < 8; i++ )
{
if( k % 2 == 0 )
{
glColor3f( 1, 1, 1 );
}
else glColor3f( 0, 0, 0 );
glRecti( x + w*i, y + h*j, 2 * x + w*i, 2 * y + h*j );
k++;
}
k++;
}
}
void onDisplay()
{
glClearColor( 0.5, 1.0, 1.0, 1.0 );
glClear( GL_COLOR_BUFFER_BIT );
glUseProgram( program );
glEnableVertexAttribArray( attribute_coord2d );
double x, y, w, h;
int k;
x = 50;
y = 50;
h = 50;
w = 50;
k = 1;
chess( x, y, w, h, k );
glFlush();
/*
GLfloat triangle_vertices[] = {
0.0, 0.8,
-0.8, -0.8,
0.8, -0.8,
};
// Describe our vertices array to OpenGL (it can't guess its format automatically)
glVertexAttribPointer(
attribute_coord2d, // attribute
2, // number of elements per vertex, here (x,y)
GL_FLOAT, // the type of each element
GL_FALSE, // take our values as-is
0, // no extra data between each position
triangle_vertices // pointer to the C array
);
// Push each element in buffer_vertices to the vertex shader
glDrawArrays(GL_TRIANGLES, 0, 3);
*/
glDisableVertexAttribArray( attribute_coord2d );
glutSwapBuffers();
}
void free_resources()
{
glDeleteProgram( program );
}
int main( int argc, char* argv[] )
{
glutInit( &argc, argv );
glutInitContextVersion( 2, 0 );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );
glutInitWindowSize( 640, 640 );
glutCreateWindow( "chesstable" );
GLenum glew_status = glewInit();
if( glew_status != GLEW_OK )
{
fprintf( stderr, "Error: %s\n", glewGetErrorString( glew_status ) );
return 1;
}
if( init_resources() )
{
glutDisplayFunc( onDisplay );
glutMainLoop();
}
free_resources();
return 0;
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I'm trying to write a modern OpenGL application from scratch and I can't get a basic Triangle to render. This is odd because I've managed this in some older code and I cant find a difference in how I've done everything.
I'm using shaders, and as far as I can tell they're compiled and linked properly.
I'm using GLFW and gl3w.
All I get from this code is my window with the clear color on it.
I'll Dump my code
Main.cpp
#include <GL/gl3w.h>
#include "Display/Display.h"
#include "Shader/Shader.h"
#include "Mesh/Mesh.h"
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#define WINDOW_TITLE "CompSci Coursework"
int main() {
//Create Display and Context
Display display( WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE );
//Create Basic Shaders
Shader basicShader( "BasicShader" );
basicShader.useShader();
//Create VAO
GLuint VAO;
glGenVertexArrays( 1, &VAO );
glBindVertexArray( VAO );
std::vector<float> verticies = {
-0.5f, -0.5f,
0.5f, -0.5f,
0.0f, 0.5f
};
//Create Mesh
Mesh triangle( verticies );
//While Open Loop
while ( !display.CheckShouldClose()) {
//Clear Buffer
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
//Draw Triangle
glDrawArrays( GL_TRIANGLES, 0, 3 );
//Update Display
display.Update();
}
return 0;
}
Display.cpp
#include <iostream>
#include <GL/gl3w.h>
#include "Display.h"
Display::Display( int width, int height, const char* title ) {
//Init GLFW
if ( glfwInit() == 0 ) {
std::cerr << "Could not initialise GLFW\n";
return;
} else {
std::cout << "GLFW initialised\n";
}
//Window Hints
glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 );
glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 2 );
glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
glfwWindowHint( GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE );
glfwWindowHint( GLFW_RESIZABLE, GL_FALSE );
//Create Window
m_window = glfwCreateWindow( width, height, title, NULL, NULL );
//Make Context
glfwMakeContextCurrent( m_window );
//Initialise GL3W
if ( gl3wInit() != 0 ) {
std::cerr << "Could not init GL3W\n";
return;
} else {
std::cout << "Initialised GL3W\n";
}
}
Display::~Display() {
//Delete Context
glfwMakeContextCurrent( 0 );
//Destroy Window
glfwDestroyWindow( m_window );
//Terminate GLFW
glfwTerminate();
}
bool Display::CheckShouldClose() {
return (bool)glfwWindowShouldClose( m_window );
}
void Display::Update() {
//Swap Buffers
glfwSwapBuffers( m_window );
//Poll Events
glfwPollEvents();
}
Mesh.cpp
#include <GL/gl3w.h>
#include <iostream>
#include "Mesh.h"
Mesh::Mesh( std::vector<float> verticies ) {
m_verticies = verticies;
//Generate VBO
glGenBuffers( 1, &m_vbo );
//Bind VBO
glBindBuffer( GL_ARRAY_BUFFER, m_vbo );;
//Pass Buffer Data
glBufferData( GL_ARRAY_BUFFER, m_verticies.size() * sizeof( float), &m_verticies[0], GL_STATIC_DRAW );
}
Mesh::~Mesh() {
glDeleteBuffers( 1, &m_vbo );
}
Shader.cpp
#include <fstream>
#include <iostream>
#include <vector>
#include <GL/gl3w.h>
#include "Shader.h"
#define SHADER_LIST { VERTEX_SHADER, FRAGMENT_SHADER }
Shader::Shader( std::string shaderName ) {
//Load Source Code
std::vector<std::string> shaderSources;
shaderSources.push_back( loadShaderSource( shaderName + ".vert" ));
shaderSources.push_back( loadShaderSource( shaderName + ".frag" ));
//Cast into C-Style Strings
const char* shaderSourcesCString[NUM_SHADER];
for ( int i : SHADER_LIST ) {
shaderSourcesCString[ i ] = shaderSources[ i ].c_str();
}
//Create Shaders
m_shaders[ VERTEX_SHADER ] = glCreateShader( GL_VERTEX_SHADER );
m_shaders[ FRAGMENT_SHADER ] = glCreateShader( GL_FRAGMENT_SHADER );
//Source Shaders
glShaderSource( m_shaders[ VERTEX_SHADER ], 1, &shaderSourcesCString[ VERTEX_SHADER ], NULL );
glShaderSource( m_shaders[ FRAGMENT_SHADER ], 1, &shaderSourcesCString[ FRAGMENT_SHADER ], NULL );
//Compile Shaders
for ( int i : SHADER_LIST ) {
glCompileShader( m_shaders[ i ] );
GLint status;
glGetShaderiv( m_shaders[ i ], GL_COMPILE_STATUS, &status );
if ( status != GL_TRUE ) {
char buffer[512];
glGetShaderInfoLog( m_shaders[ i ], 512, NULL, buffer );
std::cerr << "Shader Compilation Error on shader " << i << ": " << buffer << "\n";
return;
}
}
//Create Program
m_program = glCreateProgram();
//Attach Shaders
for ( int i : SHADER_LIST ) {
glAttachShader( m_program, m_shaders[ i ] );
}
//Link Shader
glLinkProgram( m_program );
//Find Link Error
{
GLint status;
glGetProgramiv(m_program, GL_LINK_STATUS, &status);
if (status != GL_TRUE){
std::cerr << "Unable to link shaders\n";
char buffer[512];
glGetProgramInfoLog(m_program, 512, NULL, buffer);
std::cerr << buffer;
return;
}
}
//Bind outColor
glBindFragDataLocation(m_program, 0, "outColor");
//Attributes
GLint posAttrib = glGetAttribLocation(m_program, "position");
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(posAttrib);
std::cout << "Shaders Compiled Successfully\n";
}
Shader::~Shader() {
for ( int i : SHADER_LIST ) {
//Detach Shader
glDetachShader( m_program, m_shaders[ i ] );
//Delete Shader
glDeleteShader( m_shaders[ i ] );
}
//Delete Program
glDeleteProgram( m_program );
}
std::string Shader::loadShaderSource( std::string filename ) {
//Locals
std::string output, line;
//Open File
std::fstream file;
file.open( "Shaders/" + filename );
//Check for error loading file
if ( file.bad()) {
std::cerr << "Could not load shader file: " << filename << "\n";
return NULL;
} else {
std::cout << "Loaded shader file: " << filename << "\n";
}
//Read file into locals
while ( file.good()) {
getline( file, line );
if ( line != "" )
output += line + "\n";
}
//Return C-String
return output;
}
void Shader::useShader() {
glUseProgram( m_program );
}
GLuint Shader::getProgram() {
return m_program;
}
These Are my shaders
Vertex Shader
#version 150 core
in vec2 position;
void main(){
gl_Position = vec4(position, 0.0, 1.0);
}
Fragment Shader
#version 150 core
out vec4 outColor;
void main(){
outColor = vec4(1.0, 1.0, 1.0, 1.0);
}
First you have to create the vertex array buffer:
std::vector< GLfloat > verticies;
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * (GLsizeiptr)verticies.size(), verticies.data(), GL_STATIC_DRAW);
Once your shader program is linked you have to determine the index of the vertex attribute(s):
GLuint prog = ...;
GLint posAttrLoc = glGetAttribLocation(prog, "position");
Before drawing, you have to bind and enable the vertex attribute(s):
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glEnableVertexAttribArray(posAttrLoc );
glVertexAttribPointer(posAttrLoc , 2, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays( GL_TRIANGLES, 0, 3 );
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am writing a program using shaders and getting some error when running the built exe.
Shader program failed to link
The fragment shader uses varying color, but previous shader does not write to it.
Out of resource error.
This is my code:
example.cpp:
// Two-Dimensional Sierpinski Gasket
// Generated using randomly selected vertices and bisection
#include "Angel.h"
const int NumTimesToSubdivide = 5;
const int NumTetraeder = 1024;
const int NumVertices = 9 * NumTetraeder;
vec4 points[NumVertices];
int Index = 0;
int fps = 20;
float angle_param = 0.5;
float etime;
GLint time_loc;
//----------------------------------------------------------------------------
void triangle(const vec4& a, const vec4& b, const vec4& c)
{
points[Index++] = a;
points[Index++] = b;
points[Index++] = c;
}
void divide_tetraeder(const vec4& a, const vec4& b, const vec4& c, const vec4& d, int count)
{
if(count > 0)
{
//compute midpoints
vec4 ab = (a + b) / 2.0;
vec4 ac = (a + c) / 2.0;
vec4 ad = (a + d) / 2.0;
vec4 bc = (b + c) / 2.0;
vec4 bd = (b + d) / 2.0;
vec4 cd = (c + d) / 2.0;
divide_tetraeder( a, ab, ac, ad, count -1);
divide_tetraeder(ab, b, bc, bd, count -1);
divide_tetraeder(ad, bd, cd, d, count -1);
divide_tetraeder(ac, bc, c, cd, count -1);
}
else
{
triangle(a,b,c);
triangle(b,d,c);
triangle(d,a,c);
}
}
void
init( void )
{
// Specifiy the vertices for the initial tetraeder
vec4 vertices[4] = {
vec4( 0.0, -1.0, -1.0, 1.0 ),
vec4( 0.866, -1.0, 0.5, 1.0 ),
vec4( 0.0, 1.0, 0.0, 1.0 ),
vec4( -0.866, -1.0, 0.5, 1.0 )
};
divide_tetraeder(vertices[0], vertices[1], vertices[2], vertices[3], NumTimesToSubdivide);
// 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), points, GL_STATIC_DRAW );
// Load shaders and use the resulting shader program
GLuint program = InitShader( "../shader/vshader_03.glsl", "../shader/fshader_03.glsl" );
glUseProgram( program );
// Initialize the vertex position attribute from the vertex shader
GLuint loc = glGetAttribLocation( program, "vPosition" );
glEnableVertexAttribArray( loc );
glVertexAttribPointer( loc, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
//Initialize the time parameter
time_loc = glGetUniformLocation(program, "time");
glClearColor( 1.0, 1.0, 1.0, 1.0 ); // white background
}
//----------------------------------------------------------------------------
void
display( void )
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // clear the window
glDrawArrays( GL_TRIANGLES, 0, NumVertices ); // draw the points
glutSwapBuffers();
}
//----------------------------------------------------------------------------
void
keyboard( unsigned char key, int x, int y )
{
switch ( key ) {
case 033:
exit( EXIT_SUCCESS );
break;
}
}
void specialKeys(int key, int x, int y)
{
switch (key ) {
case GLUT_KEY_UP:
fps += 1;
std::cout << "fps: " << fps << std::endl;
break;
case GLUT_KEY_DOWN:
if(fps > 1) fps -= 1;
std::cout << "fps: " << fps << std::endl;
break;
case GLUT_KEY_LEFT:
angle_param -= 0.05;
std::cout << "angle_param: " << angle_param << std::endl;
break;
case GLUT_KEY_RIGHT:
angle_param += 0.05;
std::cout << "angle_param: " << angle_param << std::endl;
break;
default:
break;
}
}
//----------------------------------------------------------------------------
void timer(int value){
static float currentangle = 0.0f;
currentangle += angle_param;
float angle = currentangle*DegreesToRadians; // small angle in radians
//**************************************************************
//Füge hier deinen code ein, der die Punkte um die z-Achse dreht und neu zur Grafikkarte hochlädt
//Benutze die Funktion RotateY um eine 4x4 Rotationsmatrix zu erzeugen
mat4 rotMat = RotateY(angle);
//Berechne die rotierten Vertices auf der CPU durch Multiplikation mit der Matrix
for(int i = 0; i < NumVertices; i++) {
points[i] = rotMat * points[i];
}
//Anzahl der Sekunden seit dem letzten Aufruf
//http://www.opengl.org/documentation/specs/glut/spec3/node70.html
etime = 0.001 * glutGet(GLUT_ELAPSED_TIME);
//Schicke diesen Wert zum Vertex Shader
glUniform1f(time_loc, etime);
//Sende alle Vertices erneut an die GPU
glBufferData( GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW );
//*******************************************************************/
glutPostRedisplay();
int delay = ceil(1000.0f / fps);
glutTimerFunc( delay,timer,0);
}
int
main( int argc, char **argv )
{
glutInit(&argc, argv);
glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
//glEnable(GL_DEPTH_TEST);
glutInitWindowSize( 512, 512 );
// If you are using freeglut, the next two lines will check if
// the code is truly 3.2. Otherwise, comment them out
//glutInitContextVersion( 3, 1 );
//glutInitContextProfile( GLUT_CORE_PROFILE );
glutCreateWindow( "Sierpinski Gasket" );
glewInit();
init();
glutDisplayFunc( display );
glutKeyboardFunc( keyboard );
glutSpecialFunc( specialKeys );
int delay = ceil(1000.0f / fps);
glutTimerFunc( delay,timer,0);
glutMainLoop();
return 0;
}
InitShader.cpp:
#include "Angel.h"
char vSource[] = "#version 130\n in vec4 vPosition;\nvoid main() {\n gl_Position = vPosition;\n}\n";
char fsource[] = "#version 130\n out vec4 color;\n void main() {\n color = vec4(1.0, 0.0, 0.0, 1.0);\n}\n";
namespace Angel {
// Create a NULL-terminated string by reading the provided file
static char*
readShaderSource(const char* shaderFile)
{
//öffne die Datei
FILE* fp = fopen(shaderFile, "r");
//wenn das nicht klappt, hör sofort auf
if ( fp == NULL ) { return NULL; }
//finde heraus wie groß in bytes die datei ist
//1. gehe zum ende der datei
fseek(fp, 0L, SEEK_END);
//2. frage nach der Größe
long size = ftell(fp);
//mache einen speicherbereich für den shadertext von ausreichender Größe
char* buf = new char[size + 1];
//gehe zum Anfang der datei
fseek(fp, 0L, SEEK_SET);
//lies das erste Zeichen
char c;
c = fgetc(fp);
//initialisiere den index für den buffer
int i = 0;
//Solange das Ende der Datei nicht erreicht ist
while(c != EOF)
{
//Zeichen abspeichern
buf[i] = c;
//Nächstes Zeichen lesen
c = fgetc(fp);
//index für den Puffer inkrementieren
i++;
}
//Am Ende den Puffer mit 0 terminieren
buf[i] = '\0';
//Datei schließen
fclose(fp);
//printf("buf is: %s",buf);
return buf;
}
// Create a GLSL program object from vertex and fragment shader files
GLuint
InitShader(const char* vShaderFile, const char* fShaderFile)
{
struct Shader {
const char* filename;
GLenum type;
GLchar* source;
} shaders[2] = {
{ vShaderFile, GL_VERTEX_SHADER, NULL },
{ fShaderFile, GL_FRAGMENT_SHADER, NULL }
};
GLuint program = glCreateProgram();
for ( int i = 0; i < 2; ++i ) {
Shader& s = shaders[i];
s.source = readShaderSource( s.filename );
if ( shaders[i].source == NULL ) {
std::cerr << "Failed to read " << s.filename << std::endl;
exit( EXIT_FAILURE );
}
/*
if(i==0) s.source = vSource;
else s.source = fsource;
*/
GLuint shader = glCreateShader( s.type );
glShaderSource( shader, 1, (const GLchar**) &s.source, NULL );
glCompileShader( shader );
GLint compiled;
glGetShaderiv( shader, GL_COMPILE_STATUS, &compiled );
if ( !compiled ) {
std::cerr << s.filename << " failed to compile:" << std::endl;
GLint logSize;
glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &logSize );
char* logMsg = new char[logSize];
glGetShaderInfoLog( shader, logSize, NULL, logMsg );
std::cerr << logMsg << std::endl;
delete [] logMsg;
exit( EXIT_FAILURE );
}
//delete [] s.source;
glAttachShader( program, shader );
}
/* link and error check */
glLinkProgram(program);
GLint linked;
glGetProgramiv( program, GL_LINK_STATUS, &linked );
if ( !linked ) {
std::cerr << "Shader program failed to link" << std::endl;
GLint logSize;
glGetProgramiv( program, GL_INFO_LOG_LENGTH, &logSize);
char* logMsg = new char[logSize];
glGetProgramInfoLog( program, logSize, NULL, logMsg );
std::cerr << logMsg << std::endl;
delete [] logMsg;
exit( EXIT_FAILURE );
}
/* use program object */
glUseProgram(program);
return program;
}
} // Close namespace Angel block
vshader_03.glsl:
#version 130
uniform float time;
in vec4 vPosition;
void main()
{
vec4 temp = vPosition;
temp.x *= (1+sin(time));
gl_Position = temp;
}
fshader_03.glsl:
#version 130
in vec4 color;
void main()
{
gl_FragColor = color;
}
Your fragment shader has a varying variable in vec4 color, but none of the preceding shader stages (the vertex shader in your case) does define an varying output out vec4 color. This is also what the error message told you. Solution: Your vertex shader must define a out vec4 color and write to it.
I attach a vertex and fragment shader to a program object, then attempt to link the said program. GL_LINK_STATUS returns false. I check the info log, it's a bunch of gibberish characters. I check GL_INFO_LOG_LENGTH, it's 0. How do I debug this situation?
//this is the end of my LoadBasicShaders function
glAttachShader(program, vertShader);
glAttachShader(program, fragShader);
glLinkProgram(program);
GLint status;
glGetProgramiv(program, GL_LINK_STATUS, &status);
if (status == GL_FALSE)
{
GLint logLength = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
std::vector<GLchar> log(logLength + 1);
glGetProgramInfoLog(program, logLength, &logLength, &log[0]);
fprintf(stderr, "%s\n\n", log);
//logLength returns 0, log returns seemingly random chars
return -3;//just my error code
}
My shaders are the simplest ones possible, since I'm just starting out.
Here's the vertex shader:
#version 330
layout(location = 0) in vec4 position;
void main()
{
gl_Position = position;
}
And here's the fragment shader:
#version 330
out vec4 outputColor;
void main()
{
outputColor = vec4(1.0, 1.0, 1.0, 1.0);
}
I use GLFW to create the OpenGL window, and GLEW to load the functions:
if (!glfwInit())
{/*error checking*/}
window = glfwCreateWindow(800, 600, "Swash", NULL, NULL);
if (!window)
{/*more error checking*/}
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
glfwSetKeyCallback(window, key_callback);
if (glewInit() != GLEW_OK)
{/*you guessed it*/}
//don't call anything that involves nonstandard OpenGL functions before this point
GLuint shaderProgram;
int shaderLoadResult = LoadBasicShaders(shaderProgram, "../res/vert.shader", "../res/frag.shader");
Use the GLFW error callback
Bullet-proof your shader loader
Use ARB_debug_output or KHR_debug
Request an explicit GL version and profile (Core/Compatibility) via glfwWindowHint()
All together (this is what I meant by posting a MCVE):
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <cstdlib>
struct GlDebugOutput
{
static void Install()
{
if( !glewIsSupported( "GL_ARB_debug_output" ) )
{
std::cerr << "GL_ARB_debug_output not supported" << std::endl;
return;
}
glEnable( GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB );
glDebugMessageCallbackARB( DebugCallback, 0 );
glDebugMessageControlARB( GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE );
}
private:
static const char* Source( GLenum source )
{
switch( source )
{
case GL_DEBUG_SOURCE_API_ARB : return "API";
case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB : return "WINDOW_SYSTEM";
case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB : return "SHADER_COMPILER";
case GL_DEBUG_SOURCE_THIRD_PARTY_ARB : return "THIRD_PARTY";
case GL_DEBUG_SOURCE_APPLICATION_ARB : return "APPLICATION";
case GL_DEBUG_SOURCE_OTHER_ARB : return "OTHER";
default : return "Unknown source";
}
}
static const char* Type( GLenum type )
{
switch( type )
{
case GL_DEBUG_TYPE_ERROR_ARB : return "ERROR";
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB : return "DEPRECATED_BEHAVIOR";
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB : return "UNDEFINED_BEHAVIOR";
case GL_DEBUG_TYPE_PORTABILITY_ARB : return "PORTABILITY";
case GL_DEBUG_TYPE_PERFORMANCE_ARB : return "PERFORMANCE";
case GL_DEBUG_TYPE_OTHER_ARB : return "OTHER";
default : return "Unknown type";
}
}
static const char* Severity( GLenum severity )
{
switch( severity )
{
case GL_DEBUG_SEVERITY_HIGH_ARB : return "HIGH";
case GL_DEBUG_SEVERITY_MEDIUM_ARB : return "MEDIUM";
case GL_DEBUG_SEVERITY_LOW_ARB : return "LOW";
default : return "Unknown severity";
}
}
static void APIENTRY DebugCallback
(
GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar* message,
const void* userParam
)
{
std::cerr << "GL_DEBUG"
<< ": " << Source( source )
<< ": " << Type( type )
<< ": " << Severity( severity )
<< ": " << message
<< std::endl;
}
};
struct Program
{
static GLuint Load( const char* vert, const char* geom, const char* frag )
{
GLuint prog = glCreateProgram();
if( vert ) AttachShader( prog, GL_VERTEX_SHADER, vert );
if( geom ) AttachShader( prog, GL_GEOMETRY_SHADER, geom );
if( frag ) AttachShader( prog, GL_FRAGMENT_SHADER, frag );
glLinkProgram( prog );
CheckStatus( prog );
return prog;
}
private:
static void CheckStatus( GLuint obj )
{
GLint status = GL_FALSE;
if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
if( status == GL_TRUE ) return;
GLchar log[ 1 << 15 ] = { 0 };
if( glIsShader(obj) ) glGetShaderInfoLog( obj, sizeof(log), NULL, log );
if( glIsProgram(obj) ) glGetProgramInfoLog( obj, sizeof(log), NULL, log );
std::cerr << log << std::endl;
exit( EXIT_FAILURE );
}
static void AttachShader( GLuint program, GLenum type, const char* src )
{
GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader );
glAttachShader( program, shader );
glDeleteShader( shader );
}
};
#define GLSL(version, shader) "#version " #version "\n" #shader
const char* vert = GLSL
(
330,
layout( location = 0 ) in vec4 position;
void main()
{
gl_Position = position;
}
);
const char* frag = GLSL
(
330,
out vec4 outputColor;
void main()
{
outputColor = vec4( 1.0, 1.0, 1.0, 1.0 );
}
);
GLuint VAO;
GLuint VBO;
GLuint prog;
void init()
{
glGenVertexArrays( 1, &VAO );
glBindVertexArray( VAO );
glGenBuffers( 1,&VBO );
glBindBuffer( GL_ARRAY_BUFFER, VBO );
float verts[] =
{
-1.0, -1.0,
1.0, -1.0,
0.0, 1.0,
};
glBufferData( GL_ARRAY_BUFFER, sizeof( verts ), verts, GL_STATIC_DRAW );
prog = Program::Load( vert, NULL, frag );
glUseProgram( prog );
glEnableVertexAttribArray( 0 );
glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 0, 0 );
}
void display()
{
glClearColor( 0, 0, 0, 1 );
glClear( GL_COLOR_BUFFER_BIT );
glUseProgram( prog );
glBindVertexArray( VAO );
glDrawArrays( GL_TRIANGLES, 0, 3 );
}
void glfwErrorCallback( int error, const char* description )
{
std::cerr << "GLFW error: " << description << std::endl;
}
int main( int argc, char** argv )
{
glfwSetErrorCallback( glfwErrorCallback );
if( GL_FALSE == glfwInit() )
{
return EXIT_FAILURE;
}
std::cout << "GLFW version : " << glfwGetVersionString() << std::endl;
glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 );
glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 3 );
glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE );
glfwWindowHint( GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE );
GLFWwindow* window = glfwCreateWindow( 640, 480, "Test", NULL, NULL );
if( NULL == window )
{
glfwTerminate();
return EXIT_FAILURE;
}
glfwMakeContextCurrent( window );
glfwSwapInterval( 1 );
glewExperimental = GL_TRUE;
const GLenum glewErr = glewInit();
if( GLEW_OK != glewErr )
{
std::cerr << "glewInit() failed: " << glewGetErrorString( glewErr ) << std::endl;
glfwTerminate();
return EXIT_FAILURE;
}
// consume spurious GL error from GLEW init
glGetError();
GlDebugOutput::Install();
init();
while( !glfwWindowShouldClose( window ) )
{
glfwPollEvents();
int w, h;
glfwGetFramebufferSize( window, &w, &h );
glViewport( 0, 0, w, h );
display();
glfwSwapBuffers( window );
}
return EXIT_SUCCESS;
}
If anything is even just a little bit off with your OpenGL implementation and/or shaders that program should scream bloody murder to stderr and exit.
Sorry for the very slow update, I've been busy with other things.
Anyways, the problem was that while writing the code, I had included the line
program = glCreateProgram();
but at some point, while tidying up, I accidentally deleted it. That's why the shaders were compiling but weren't linking, they weren't being linked to a program object.
I have looked through the examples in the Glui package, but I need help with loading (.m) file which is 3D model
this is the sample codes....
#include <iostream>
#include <GL/glut.h>
#include <cstdlib>
using namespace std;
void createMenu(void);
void menu(int value);
void disp(void);
static int win;
static int menid;
static int submenid;
static int primitive = 0; // global variable for the geometric primitive
int main(int argc, char **argv){
// normal initialisation
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE);
glutInitWindowSize(500,500);
glutInitWindowPosition(100,100);
win = glutCreateWindow("GLUT MENU");
// put all the menu functions in one nice procedure
createMenu();
// set the clearcolor and the callback
glClearColor(0.0,0.0,0.0,0.0);
// register your drawing function
glutDisplayFunc(disp);
// enter the main loop
glutMainLoop();
return 1;
}
//#define USE_SUB_MENU
void createMenu(void){
//#ifdef USE_SUB_MENU
// step 1: Create a submenu, this has to be done first.
submenid = glutCreateMenu(menu); // pass the function "menu" to glutCreateMenu
// Add sub menu entry
glutAddMenuEntry("Teapot", 2);
glutAddMenuEntry("Cube", 3);
glutAddMenuEntry("Torus", 4);
// step 2: Create the main menu, this menu becomes the current menu
menid = glutCreateMenu(menu);
// Create an entry
glutAddMenuEntry("Clear", 1);
glutAddSubMenu("Draw", submenid);
// Create an entry
glutAddMenuEntry("Quit", 0);
// Let the menu respond on the right mouse button
glutAttachMenu(GLUT_RIGHT_BUTTON);
//#else
menid = glutCreateMenu(menu);
// Create an entry
glutAddMenuEntry("Clear", 1);
glutAddMenuEntry("Teapot", 2);
glutAddMenuEntry("Cube", 3);
glutAddMenuEntry("Torus", 4);
// Create an entry
glutAddMenuEntry("Quit", 0);
// Let the menu respond on the right mouse button
glutAttachMenu(GLUT_RIGHT_BUTTON);
//#endif
}
void disp(void){
// Just clean the screen
// this has to be called everytime when you draw sth
glClear(GL_COLOR_BUFFER_BIT);
// draw what the user asked
if(primitive == 1){ // clear the screen
glutPostRedisplay();
}else if(primitive == 2){ // draw the teapot
glutWireTeapot(0.5);
}else if(primitive == 3){ // draw the cube
glutWireCube(0.5);
}else if(primitive == 4){ // draw the torus
glutWireTorus(0.3,0.6,100,100);
}
glFlush();
}
void menu(int value){
if(value == 0){ // the user clicks 'quit'
glutDestroyWindow(win);
exit(0);
}else{
primitive=value; // set the geometric primitive
}
// you would want to redraw now
glutPostRedisplay();
}
I really don't know how to do T_T, requirment is to load .m files using opengl, glut, glui.... So, I need help to load it with opengl without crashing then done.
You'll need a parser for your .M files.
I couldn't find a spec anywhere so I've taken a guess at the format:
#include <glm/glm.hpp>
using namespace glm;
struct Vertex
{
vec3 position;
vec3 normal;
};
vector< Vertex > LoadM( istream& in )
{
vector< Vertex > verts;
map< int, vec3 > positions;
map< int, vec3 > normals;
string lineStr;
while( getline( in, lineStr ) )
{
istringstream lineSS( lineStr );
string lineType;
lineSS >> lineType;
// vertex
if( lineType == "Vertex" )
{
int idx;
float x = 0, y = 0, z = 0;
lineSS >> idx >> x >> y >> z;
positions[ idx ] = vec3( x, y, z );
}
// face
if( lineType == "Face" )
{
int indexes[ 3 ];
int idx;
lineSS >> idx >> indexes[0] >> indexes[1] >> indexes[2];
// http://www.opengl.org/wiki/Calculating_a_Surface_Normal
vec3 U( positions[ indexes[1] ] - positions[ indexes[0] ] );
vec3 V( positions[ indexes[2] ] - positions[ indexes[0] ] );
vec3 faceNormal = normalize( cross( U, V ) );
for( size_t j = 0; j < 3; ++j )
{
Vertex vert;
vert.position = vec3( positions[ indexes[j] ] );
vert.normal = faceNormal;
verts.push_back( vert );
}
}
}
return verts;
}
Used in context:
#include <GL/glut.h>
#include <glm/glm.hpp>
#include <glm/gtx/component_wise.hpp>
#include <vector>
#include <map>
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
using namespace glm;
struct Vertex
{
vec3 position;
vec3 normal;
};
vector< Vertex > LoadM( istream& in )
{
vector< Vertex > verts;
map< int, vec3 > positions;
string lineStr;
while( getline( in, lineStr ) )
{
istringstream lineSS( lineStr );
string lineType;
lineSS >> lineType;
// parse vertex line
if( lineType == "Vertex" )
{
int idx = 0;
float x = 0, y = 0, z = 0;
lineSS >> idx >> x >> y >> z;
positions.insert( make_pair( idx, vec3( x, y, z ) ) );
}
// parse face line
if( lineType == "Face" )
{
int indexes[ 3 ] = { 0 };
int idx = 0;
lineSS >> idx >> indexes[0] >> indexes[1] >> indexes[2];
// http://www.opengl.org/wiki/Calculating_a_Surface_Normal
vec3 U( positions[ indexes[1] ] - positions[ indexes[0] ] );
vec3 V( positions[ indexes[2] ] - positions[ indexes[0] ] );
vec3 faceNormal = normalize( cross( U, V ) );
for( size_t j = 0; j < 3; ++j )
{
Vertex vert;
vert.position = vec3( positions[ indexes[j] ] );
vert.normal = faceNormal;
verts.push_back( vert );
}
}
}
return verts;
}
// mouse state
int btn;
ivec2 startMouse;
ivec2 startRot, curRot;
ivec2 startTrans, curTrans;
void mouse(int button, int state, int x, int y )
{
y = glutGet( GLUT_WINDOW_HEIGHT ) - y;
if( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN )
{
btn = button;
startMouse = ivec2( x, y );
startRot = curRot;
}
if( button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN )
{
btn = button;
startMouse = ivec2( x, y );
startTrans = curTrans;
}
}
void motion( int x, int y )
{
y = glutGet( GLUT_WINDOW_HEIGHT ) - y;
ivec2 curMouse( x, y );
if( btn == GLUT_LEFT_BUTTON )
{
curRot = startRot + ( curMouse - startMouse );
}
else if( btn == GLUT_RIGHT_BUTTON )
{
curTrans = startTrans + ( curMouse - startMouse );
}
glutPostRedisplay();
}
vector< Vertex > model;
void display()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
double w = glutGet( GLUT_WINDOW_WIDTH );
double h = glutGet( GLUT_WINDOW_HEIGHT );
double ar = w / h;
// "pan"
glTranslatef( curTrans.x / w * 2, curTrans.y / h * 2, 0 );
gluPerspective( 60, ar, 0.1, 20 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glTranslatef( 0, 0, -10 );
glPushMatrix();
// apply mouse rotation
glRotatef( curRot.x % 360, 0, 1, 0 );
glRotatef( -curRot.y % 360, 1, 0, 0 );
glColor3ub( 255, 0, 0 );
// draw model
glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_NORMAL_ARRAY );
glVertexPointer( 3, GL_FLOAT, sizeof(Vertex), &model[0].position );
glNormalPointer( GL_FLOAT, sizeof(Vertex), &model[0].normal );
glDrawArrays( GL_TRIANGLES, 0, model.size() );
glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_NORMAL_ARRAY );
// draw bounding cube
glDisable( GL_LIGHTING );
glColor3ub( 255, 255, 255 );
glutWireCube( 7 );
glEnable( GL_LIGHTING );
glPopMatrix();
glutSwapBuffers();
}
// return the x/y/z min/max of some geometry
template< typename Vec >
pair< Vec, Vec > GetExtents
(
const Vec* pts,
size_t stride,
size_t count
)
{
typedef typename Vec::value_type Scalar;
Vec pmin( std::numeric_limits< Scalar >::max() );
Vec pmax( std::min( std::numeric_limits< Scalar >::min(),
(Scalar)-std::numeric_limits< Scalar >::max() ) );
// find extents
unsigned char* base = (unsigned char*)pts;
for( size_t i = 0; i < count; ++i )
{
const Vec& pt = *(Vec*)base;
pmin = glm::min( pmin, pt );
pmax = glm::max( pmax, pt );
base += stride;
}
return make_pair( pmin, pmax );
}
// centers geometry around the origin
// and scales it to fit in a size^3 box
template< typename Vec >
void CenterAndScale
(
Vec* pts,
size_t stride,
size_t count,
const typename Vec::value_type& size
)
{
typedef typename Vec::value_type Scalar;
// get min/max extents
pair< Vec, Vec > exts = GetExtents( pts, stride, count );
// center and scale
const Vec center = ( exts.first * Scalar( 0.5 ) ) + ( exts.second * Scalar( 0.5f ) );
const Scalar factor = size / glm::compMax( exts.second - exts.first );
unsigned char* base = (unsigned char*)pts;
for( size_t i = 0; i < count; ++i )
{
Vec& pt = *(Vec*)base;
pt = ((pt - center) * factor);
base += stride;
}
}
int main( int argc, char **argv )
{
ifstream ifile( "bunny.m" );
model = LoadM( ifile );
if( model.empty() )
{
cerr << "Empty model!" << endl;
return -1;
}
CenterAndScale( &model[0].position, sizeof( Vertex ), model.size(), 7 );
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
glutInitWindowSize( 640, 480 );
glutCreateWindow( "GLUT" );
glutDisplayFunc( display );
glutMouseFunc( mouse );
glutMotionFunc( motion );
glEnable( GL_DEPTH_TEST );
// set up "headlamp"-like light
glShadeModel( GL_SMOOTH );
glEnable( GL_COLOR_MATERIAL );
glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ) ;
glEnable( GL_LIGHTING );
glEnable( GL_LIGHT0 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
GLfloat position[] = { 0, 0, 1, 0 };
glLightfv( GL_LIGHT0, GL_POSITION, position );
glPolygonMode( GL_FRONT, GL_FILL );
glPolygonMode( GL_BACK, GL_LINE );
glutMainLoop();
return 0;
}