861 lines
24 KiB
C++
861 lines
24 KiB
C++
/*
|
|
Copyright (c) 2012 Advanced Micro Devices, Inc.
|
|
|
|
This software is provided 'as-is', without any express or implied warranty.
|
|
In no event will the authors be held liable for any damages arising from the use of this software.
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
including commercial applications, and to alter it and redistribute it freely,
|
|
subject to the following restrictions:
|
|
|
|
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
|
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
|
3. This notice may not be removed or altered from any source distribution.
|
|
*/
|
|
//Originally written by Erwin Coumans
|
|
|
|
#include "OpenGLInclude.h"
|
|
#include "GLInstancingRenderer.h"
|
|
|
|
#include <string.h>
|
|
#include "DemoSettings.h"
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
#include "LinearMath/btVector3.h"
|
|
#include "LinearMath/btQuaternion.h"
|
|
#include "LinearMath/btQuickprof.h"
|
|
#include "LinearMath/btMatrix3x3.h"
|
|
|
|
#include "../../opencl/gpu_rigidbody_pipeline/btGpuNarrowphaseAndSolver.h"//for MAX_CONVEX_BODIES_CL
|
|
|
|
struct btGraphicsInstance
|
|
{
|
|
GLuint m_cube_vao;
|
|
GLuint m_index_vbo;
|
|
int m_numIndices;
|
|
int m_numVertices;
|
|
|
|
int m_numGraphicsInstances;
|
|
|
|
int m_instanceOffset;
|
|
int m_vertexArrayOffset;
|
|
|
|
btGraphicsInstance() :m_cube_vao(-1),m_index_vbo(-1),m_numIndices(-1),m_numVertices(-1),m_numGraphicsInstances(0),m_instanceOffset(0),m_vertexArrayOffset(0)
|
|
{
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
bool m_ortho = false;
|
|
int m_glutScreenWidth = 1024;
|
|
int m_glutScreenHeight = 768;
|
|
|
|
|
|
|
|
extern int gShapeIndex;
|
|
|
|
|
|
btVector3 m_cameraPosition(0,0,0);//will be overridden by a position computed from azi/ele
|
|
btVector3 m_cameraTargetPosition(30,-5,-20);
|
|
btScalar m_cameraDistance = 95;
|
|
btVector3 m_cameraUp(0,1,0);
|
|
float m_azi=95.f;
|
|
float m_ele=15.f;
|
|
|
|
|
|
|
|
|
|
int VBOsize =0;
|
|
|
|
|
|
|
|
struct InternalDataRenderer
|
|
{
|
|
GLfloat* m_instance_positions_ptr;
|
|
GLfloat* m_instance_quaternion_ptr;
|
|
GLfloat* m_instance_colors_ptr;
|
|
GLfloat* m_instance_scale_ptr;
|
|
|
|
InternalDataRenderer() :m_instance_positions_ptr (0),m_instance_quaternion_ptr(0),m_instance_colors_ptr(0),m_instance_scale_ptr(0)
|
|
{
|
|
}
|
|
|
|
};
|
|
|
|
static GLuint instancingShader; // The instancing renderer
|
|
|
|
GLuint cube_vbo;
|
|
|
|
static GLuint m_texturehandle;
|
|
|
|
static bool done = false;
|
|
static GLint angle_loc = 0;
|
|
static GLint ModelViewMatrix;
|
|
static GLint ProjectionMatrix;
|
|
|
|
|
|
|
|
GLInstancingRenderer::GLInstancingRenderer()
|
|
{
|
|
|
|
m_data = new InternalDataRenderer;
|
|
|
|
m_data->m_instance_positions_ptr = (GLfloat*)new float[MAX_CONVEX_BODIES_CL*4];
|
|
m_data->m_instance_quaternion_ptr = (GLfloat*)new float[MAX_CONVEX_BODIES_CL*4];
|
|
m_data->m_instance_colors_ptr = (GLfloat*)new float[MAX_CONVEX_BODIES_CL*4];
|
|
m_data->m_instance_scale_ptr = (GLfloat*)new float[MAX_CONVEX_BODIES_CL*3];
|
|
|
|
}
|
|
|
|
GLInstancingRenderer::~GLInstancingRenderer()
|
|
{
|
|
delete m_data;
|
|
}
|
|
|
|
|
|
static GLint uniform_texture_diffuse = 0;
|
|
|
|
//used for dynamic loading from disk (default switched off)
|
|
#define MAX_SHADER_LENGTH 8192
|
|
static GLubyte shaderText[MAX_SHADER_LENGTH];
|
|
|
|
static const char* vertexShader= \
|
|
"#version 330\n"
|
|
"precision highp float;\n"
|
|
"\n"
|
|
"\n"
|
|
"\n"
|
|
"layout (location = 0) in vec4 position;\n"
|
|
"layout (location = 1) in vec4 instance_position;\n"
|
|
"layout (location = 2) in vec4 instance_quaternion;\n"
|
|
"layout (location = 3) in vec2 uvcoords;\n"
|
|
"layout (location = 4) in vec3 vertexnormal;\n"
|
|
"layout (location = 5) in vec4 instance_color;\n"
|
|
"layout (location = 6) in vec3 instance_scale;\n"
|
|
"\n"
|
|
"\n"
|
|
"uniform float angle = 0.0;\n"
|
|
"uniform mat4 ModelViewMatrix;\n"
|
|
"uniform mat4 ProjectionMatrix;\n"
|
|
"\n"
|
|
"out Fragment\n"
|
|
"{\n"
|
|
" vec4 color;\n"
|
|
"} fragment;\n"
|
|
"\n"
|
|
"out Vert\n"
|
|
"{\n"
|
|
" vec2 texcoord;\n"
|
|
"} vert;\n"
|
|
"\n"
|
|
"\n"
|
|
"vec4 quatMul ( in vec4 q1, in vec4 q2 )\n"
|
|
"{\n"
|
|
" vec3 im = q1.w * q2.xyz + q1.xyz * q2.w + cross ( q1.xyz, q2.xyz );\n"
|
|
" vec4 dt = q1 * q2;\n"
|
|
" float re = dot ( dt, vec4 ( -1.0, -1.0, -1.0, 1.0 ) );\n"
|
|
" return vec4 ( im, re );\n"
|
|
"}\n"
|
|
"\n"
|
|
"vec4 quatFromAxisAngle(vec4 axis, in float angle)\n"
|
|
"{\n"
|
|
" float cah = cos(angle*0.5);\n"
|
|
" float sah = sin(angle*0.5);\n"
|
|
" float d = inversesqrt(dot(axis,axis));\n"
|
|
" vec4 q = vec4(axis.x*sah*d,axis.y*sah*d,axis.z*sah*d,cah);\n"
|
|
" return q;\n"
|
|
"}\n"
|
|
"//\n"
|
|
"// vector rotation via quaternion\n"
|
|
"//\n"
|
|
"vec4 quatRotate3 ( in vec3 p, in vec4 q )\n"
|
|
"{\n"
|
|
" vec4 temp = quatMul ( q, vec4 ( p, 0.0 ) );\n"
|
|
" return quatMul ( temp, vec4 ( -q.x, -q.y, -q.z, q.w ) );\n"
|
|
"}\n"
|
|
"vec4 quatRotate ( in vec4 p, in vec4 q )\n"
|
|
"{\n"
|
|
" vec4 temp = quatMul ( q, p );\n"
|
|
" return quatMul ( temp, vec4 ( -q.x, -q.y, -q.z, q.w ) );\n"
|
|
"}\n"
|
|
"\n"
|
|
"out vec3 lightDir,normal,ambient;\n"
|
|
"\n"
|
|
"void main(void)\n"
|
|
"{\n"
|
|
" vec4 q = instance_quaternion;\n"
|
|
" ambient = vec3(0.3,.3,0.3);\n"
|
|
" \n"
|
|
" \n"
|
|
" vec4 local_normal = (quatRotate3( vertexnormal,q));\n"
|
|
" vec3 light_pos = vec3(-0.8,1,-0.6);\n"
|
|
" normal = local_normal.xyz;\n"//normalize(ModelViewMatrix * local_normal).xyz;\n"
|
|
"\n"
|
|
" lightDir = normalize(light_pos);//gl_LightSource[0].position.xyz));\n"
|
|
"// lightDir = normalize(vec3(gl_LightSource[0].position));\n"
|
|
" \n"
|
|
" vec4 axis = vec4(1,1,1,0);\n"
|
|
" vec4 localcoord = quatRotate3( position.xyz*instance_scale,q);\n"
|
|
" vec4 vertexPos = ProjectionMatrix * ModelViewMatrix *(instance_position+localcoord);\n"
|
|
"\n"
|
|
" gl_Position = vertexPos;\n"
|
|
" \n"
|
|
" fragment.color = instance_color;\n"
|
|
" vert.texcoord = uvcoords;\n"
|
|
"}\n"
|
|
;
|
|
|
|
|
|
static const char* fragmentShader= \
|
|
"#version 330\n"
|
|
"precision highp float;\n"
|
|
"\n"
|
|
"in Fragment\n"
|
|
"{\n"
|
|
" vec4 color;\n"
|
|
"} fragment;\n"
|
|
"\n"
|
|
"in Vert\n"
|
|
"{\n"
|
|
" vec2 texcoord;\n"
|
|
"} vert;\n"
|
|
"\n"
|
|
"uniform sampler2D Diffuse;\n"
|
|
"\n"
|
|
"in vec3 lightDir,normal,ambient;\n"
|
|
"\n"
|
|
"out vec4 color;\n"
|
|
"\n"
|
|
"void main_textured(void)\n"
|
|
"{\n"
|
|
" color = texture2D(Diffuse,vert.texcoord);//fragment.color;\n"
|
|
"}\n"
|
|
"\n"
|
|
"void main(void)\n"
|
|
"{\n"
|
|
" vec4 texel = fragment.color*texture2D(Diffuse,vert.texcoord);//fragment.color;\n"
|
|
" vec3 ct,cf;\n"
|
|
" float intensity,at,af;\n"
|
|
" intensity = max(dot(lightDir,normalize(normal)),.2);\n"
|
|
" cf = intensity*vec3(1.0,1.0,1.0)+ambient;"
|
|
" af = 1.0;\n"
|
|
" \n"
|
|
" ct = texel.rgb;\n"
|
|
" at = texel.a;\n"
|
|
" \n"
|
|
" color = vec4(ct * cf, at * af); \n"
|
|
"}\n"
|
|
;
|
|
|
|
|
|
// Load the shader from the source text
|
|
void gltLoadShaderSrc(const char *szShaderSrc, GLuint shader)
|
|
{
|
|
GLchar *fsStringPtr[1];
|
|
|
|
fsStringPtr[0] = (GLchar *)szShaderSrc;
|
|
glShaderSource(shader, 1, (const GLchar **)fsStringPtr, NULL);
|
|
}
|
|
|
|
|
|
GLuint gltLoadShaderPair(const char *szVertexProg, const char *szFragmentProg)
|
|
{
|
|
// Temporary Shader objects
|
|
GLuint hVertexShader;
|
|
GLuint hFragmentShader;
|
|
GLuint hReturn = 0;
|
|
GLint testVal;
|
|
|
|
// Create shader objects
|
|
hVertexShader = glCreateShader(GL_VERTEX_SHADER);
|
|
hFragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
|
|
|
gltLoadShaderSrc(vertexShader, hVertexShader);
|
|
gltLoadShaderSrc(fragmentShader, hFragmentShader);
|
|
|
|
// Compile them
|
|
glCompileShader(hVertexShader);
|
|
glCompileShader(hFragmentShader);
|
|
|
|
// Check for errors
|
|
glGetShaderiv(hVertexShader, GL_COMPILE_STATUS, &testVal);
|
|
if(testVal == GL_FALSE)
|
|
{
|
|
char temp[256] = "";
|
|
glGetShaderInfoLog( hVertexShader, 256, NULL, temp);
|
|
fprintf( stderr, "Compile failed:\n%s\n", temp);
|
|
assert(0);
|
|
exit(0);
|
|
glDeleteShader(hVertexShader);
|
|
glDeleteShader(hFragmentShader);
|
|
return (GLuint)NULL;
|
|
}
|
|
|
|
glGetShaderiv(hFragmentShader, GL_COMPILE_STATUS, &testVal);
|
|
if(testVal == GL_FALSE)
|
|
{
|
|
char temp[256] = "";
|
|
glGetShaderInfoLog( hFragmentShader, 256, NULL, temp);
|
|
fprintf( stderr, "Compile failed:\n%s\n", temp);
|
|
assert(0);
|
|
exit(0);
|
|
glDeleteShader(hVertexShader);
|
|
glDeleteShader(hFragmentShader);
|
|
return (GLuint)NULL;
|
|
}
|
|
|
|
// Link them - assuming it works...
|
|
hReturn = glCreateProgram();
|
|
glAttachShader(hReturn, hVertexShader);
|
|
glAttachShader(hReturn, hFragmentShader);
|
|
|
|
glLinkProgram(hReturn);
|
|
|
|
// These are no longer needed
|
|
glDeleteShader(hVertexShader);
|
|
glDeleteShader(hFragmentShader);
|
|
|
|
// Make sure link worked too
|
|
glGetProgramiv(hReturn, GL_LINK_STATUS, &testVal);
|
|
if(testVal == GL_FALSE)
|
|
{
|
|
glDeleteProgram(hReturn);
|
|
return (GLuint)NULL;
|
|
}
|
|
|
|
return hReturn;
|
|
}
|
|
|
|
|
|
void GLInstancingRenderer::writeTransforms()
|
|
{
|
|
glBindBuffer(GL_ARRAY_BUFFER, cube_vbo);
|
|
glFlush();
|
|
|
|
char* orgBase = (char*)glMapBuffer( GL_ARRAY_BUFFER,GL_READ_WRITE);
|
|
|
|
int totalNumInstances= 0;
|
|
|
|
for (int k=0;k<m_graphicsInstances.size();k++)
|
|
{
|
|
btGraphicsInstance* gfxObj = m_graphicsInstances[k];
|
|
totalNumInstances+=gfxObj->m_numGraphicsInstances;
|
|
}
|
|
|
|
|
|
|
|
for (int k=0;k<m_graphicsInstances.size();k++)
|
|
{
|
|
//int k=0;
|
|
btGraphicsInstance* gfxObj = m_graphicsInstances[k];
|
|
|
|
|
|
|
|
int POSITION_BUFFER_SIZE = (totalNumInstances*sizeof(float)*4);
|
|
int ORIENTATION_BUFFER_SIZE = (totalNumInstances*sizeof(float)*4);
|
|
int COLOR_BUFFER_SIZE = (totalNumInstances*sizeof(float)*4);
|
|
int SCALE_BUFFER_SIZE = (totalNumInstances*sizeof(float)*3);
|
|
|
|
char* base = orgBase;
|
|
|
|
float* positions = (float*)(base+SHAPE_BUFFER_SIZE);
|
|
float* orientations = (float*)(base+SHAPE_BUFFER_SIZE + POSITION_BUFFER_SIZE);
|
|
float* colors= (float*)(base+SHAPE_BUFFER_SIZE + POSITION_BUFFER_SIZE+ORIENTATION_BUFFER_SIZE);
|
|
float* scaling= (float*)(base+SHAPE_BUFFER_SIZE + POSITION_BUFFER_SIZE+ORIENTATION_BUFFER_SIZE+COLOR_BUFFER_SIZE);
|
|
|
|
static int offset=0;
|
|
//offset++;
|
|
|
|
|
|
for (int i=0;i<gfxObj->m_numGraphicsInstances;i++)
|
|
{
|
|
|
|
int srcIndex=i+gfxObj->m_instanceOffset;
|
|
|
|
positions[srcIndex*4] = m_data->m_instance_positions_ptr[srcIndex*4];
|
|
positions[srcIndex*4+1] = m_data->m_instance_positions_ptr[srcIndex*4+1];
|
|
positions[srcIndex*4+2] = m_data->m_instance_positions_ptr[srcIndex*4+2];
|
|
positions[srcIndex*4+3] = m_data->m_instance_positions_ptr[srcIndex*4+3];
|
|
|
|
orientations[srcIndex*4]=m_data->m_instance_quaternion_ptr[srcIndex*4];
|
|
orientations[srcIndex*4+1]=m_data->m_instance_quaternion_ptr[srcIndex*4+1];
|
|
orientations[srcIndex*4+2]=m_data->m_instance_quaternion_ptr[srcIndex*4+2];
|
|
orientations[srcIndex*4+3]=m_data->m_instance_quaternion_ptr[srcIndex*4+3];
|
|
|
|
colors[srcIndex*4]=m_data->m_instance_colors_ptr[srcIndex*4];
|
|
colors[srcIndex*4+1]=m_data->m_instance_colors_ptr[srcIndex*4+1];
|
|
colors[srcIndex*4+2]=m_data->m_instance_colors_ptr[srcIndex*4+2];
|
|
colors[srcIndex*4+3]=m_data->m_instance_colors_ptr[srcIndex*4+3];
|
|
|
|
scaling[srcIndex*3]=m_data->m_instance_scale_ptr[srcIndex*3];
|
|
scaling[srcIndex*3+1]=m_data->m_instance_scale_ptr[srcIndex*3+1];
|
|
scaling[srcIndex*3+2]=m_data->m_instance_scale_ptr[srcIndex*3+2];
|
|
|
|
}
|
|
}
|
|
|
|
glUnmapBuffer( GL_ARRAY_BUFFER);
|
|
//if this glFinish is removed, the animation is not always working/blocks
|
|
//@todo: figure out why
|
|
glFlush();
|
|
}
|
|
|
|
int GLInstancingRenderer::registerGraphicsInstance(int shapeIndex, const float* position, const float* quaternion, const float* color, const float* scaling)
|
|
{
|
|
btGraphicsInstance* gfxObj = m_graphicsInstances[shapeIndex];
|
|
|
|
int index = gfxObj->m_numGraphicsInstances + gfxObj->m_instanceOffset;
|
|
|
|
|
|
|
|
m_data->m_instance_positions_ptr[index*4]=position[0];
|
|
m_data->m_instance_positions_ptr[index*4+1]=position[1];
|
|
m_data->m_instance_positions_ptr[index*4+2]=position[2];
|
|
m_data->m_instance_positions_ptr[index*4+3]=1;
|
|
|
|
m_data->m_instance_quaternion_ptr[index*4]=quaternion[0];
|
|
m_data->m_instance_quaternion_ptr[index*4+1]=quaternion[1];
|
|
m_data->m_instance_quaternion_ptr[index*4+2]=quaternion[2];
|
|
m_data->m_instance_quaternion_ptr[index*4+3]=quaternion[3];
|
|
|
|
m_data->m_instance_colors_ptr[index*4]=color[0];
|
|
m_data->m_instance_colors_ptr[index*4+1]=color[1];
|
|
m_data->m_instance_colors_ptr[index*4+2]=color[2];
|
|
m_data->m_instance_colors_ptr[index*4+3]=color[3];
|
|
|
|
m_data->m_instance_scale_ptr[index*3] = scaling[0];
|
|
m_data->m_instance_scale_ptr[index*3+1] = scaling[1];
|
|
m_data->m_instance_scale_ptr[index*3+2] = scaling[2];
|
|
|
|
gfxObj->m_numGraphicsInstances++;
|
|
return gfxObj->m_numGraphicsInstances;
|
|
}
|
|
|
|
|
|
int GLInstancingRenderer::registerShape(const float* vertices, int numvertices, const int* indices, int numIndices)
|
|
{
|
|
btGraphicsInstance* gfxObj = new btGraphicsInstance;
|
|
|
|
if (m_graphicsInstances.size())
|
|
{
|
|
btGraphicsInstance* prevObj = m_graphicsInstances[m_graphicsInstances.size()-1];
|
|
gfxObj->m_instanceOffset = prevObj->m_instanceOffset + prevObj->m_numGraphicsInstances;
|
|
gfxObj->m_vertexArrayOffset = prevObj->m_vertexArrayOffset + prevObj->m_numVertices;
|
|
} else
|
|
{
|
|
gfxObj->m_instanceOffset = 0;
|
|
}
|
|
|
|
m_graphicsInstances.push_back(gfxObj);
|
|
gfxObj->m_numIndices = numIndices;
|
|
gfxObj->m_numVertices = numvertices;
|
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, cube_vbo);
|
|
char* dest= (char*)glMapBuffer( GL_ARRAY_BUFFER,GL_WRITE_ONLY);//GL_WRITE_ONLY
|
|
int vertexStrideInBytes = 9*sizeof(float);
|
|
int sz = numvertices*vertexStrideInBytes;
|
|
memcpy(dest+vertexStrideInBytes*gfxObj->m_vertexArrayOffset,vertices,sz);
|
|
glUnmapBuffer( GL_ARRAY_BUFFER);
|
|
|
|
glGenBuffers(1, &gfxObj->m_index_vbo);
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gfxObj->m_index_vbo);
|
|
int indexBufferSizeInBytes = gfxObj->m_numIndices*sizeof(int);
|
|
|
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexBufferSizeInBytes, NULL, GL_STATIC_DRAW);
|
|
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,0,indexBufferSizeInBytes,indices);
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
|
|
|
glGenVertexArrays(1, &gfxObj->m_cube_vao);
|
|
glBindVertexArray(gfxObj->m_cube_vao);
|
|
glBindBuffer(GL_ARRAY_BUFFER, cube_vbo);
|
|
glBindVertexArray(0);
|
|
glBindBuffer(GL_ARRAY_BUFFER,0);
|
|
glBindVertexArray(0);
|
|
|
|
|
|
return m_graphicsInstances.size()-1;
|
|
}
|
|
|
|
|
|
|
|
|
|
void GLInstancingRenderer::InitShaders()
|
|
{
|
|
|
|
int POSITION_BUFFER_SIZE = (MAX_CONVEX_BODIES_CL*sizeof(float)*4);
|
|
int ORIENTATION_BUFFER_SIZE = (MAX_CONVEX_BODIES_CL*sizeof(float)*4);
|
|
int COLOR_BUFFER_SIZE = (MAX_CONVEX_BODIES_CL*sizeof(float)*4);
|
|
int SCALE_BUFFER_SIZE = (MAX_CONVEX_BODIES_CL*sizeof(float)*3);
|
|
|
|
|
|
instancingShader = gltLoadShaderPair(vertexShader,fragmentShader);
|
|
|
|
glLinkProgram(instancingShader);
|
|
glUseProgram(instancingShader);
|
|
angle_loc = glGetUniformLocation(instancingShader, "angle");
|
|
ModelViewMatrix = glGetUniformLocation(instancingShader, "ModelViewMatrix");
|
|
ProjectionMatrix = glGetUniformLocation(instancingShader, "ProjectionMatrix");
|
|
uniform_texture_diffuse = glGetUniformLocation(instancingShader, "Diffuse");
|
|
|
|
GLuint offset = 0;
|
|
|
|
|
|
glGenBuffers(1, &cube_vbo);
|
|
glBindBuffer(GL_ARRAY_BUFFER, cube_vbo);
|
|
|
|
|
|
int size = SHAPE_BUFFER_SIZE + POSITION_BUFFER_SIZE+ORIENTATION_BUFFER_SIZE+COLOR_BUFFER_SIZE+SCALE_BUFFER_SIZE;
|
|
VBOsize = size;
|
|
|
|
glBufferData(GL_ARRAY_BUFFER, size, 0, GL_DYNAMIC_DRAW);//GL_STATIC_DRAW);
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER,0);
|
|
glBindVertexArray(0);
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
void myinit()
|
|
{
|
|
GLint err = glGetError();
|
|
|
|
// GLfloat light_ambient[] = { btScalar(0.2), btScalar(0.2), btScalar(0.2), btScalar(1.0) };
|
|
GLfloat light_ambient[] = { btScalar(1.0), btScalar(1.2), btScalar(0.2), btScalar(1.0) };
|
|
|
|
GLfloat light_diffuse[] = { btScalar(1.0), btScalar(1.0), btScalar(1.0), btScalar(1.0) };
|
|
GLfloat light_specular[] = { btScalar(1.0), btScalar(1.0), btScalar(1.0), btScalar(1.0 )};
|
|
/* light_position is NOT default value */
|
|
GLfloat light_position0[] = { btScalar(10000.0), btScalar(10000.0), btScalar(10000.0), btScalar(0.0 )};
|
|
GLfloat light_position1[] = { btScalar(-1.0), btScalar(-10.0), btScalar(-1.0), btScalar(0.0) };
|
|
|
|
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
|
|
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
|
|
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
|
|
glLightfv(GL_LIGHT0, GL_POSITION, light_position0);
|
|
|
|
glLightfv(GL_LIGHT1, GL_AMBIENT, light_ambient);
|
|
glLightfv(GL_LIGHT1, GL_DIFFUSE, light_diffuse);
|
|
glLightfv(GL_LIGHT1, GL_SPECULAR, light_specular);
|
|
glLightfv(GL_LIGHT1, GL_POSITION, light_position1);
|
|
|
|
glEnable(GL_LIGHTING);
|
|
glEnable(GL_LIGHT0);
|
|
glEnable(GL_LIGHT1);
|
|
|
|
|
|
// glShadeModel(GL_FLAT);//GL_SMOOTH);
|
|
glShadeModel(GL_SMOOTH);
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
glDepthFunc(GL_LESS);
|
|
|
|
glClearColor(float(0.7),float(0.7),float(0.7),float(0));
|
|
glEnable(GL_LIGHTING);
|
|
glEnable(GL_LIGHT0);
|
|
|
|
|
|
static bool m_textureenabled = true;
|
|
static bool m_textureinitialized = false;
|
|
|
|
|
|
if(m_textureenabled)
|
|
{
|
|
if(!m_textureinitialized)
|
|
{
|
|
glActiveTexture(GL_TEXTURE0);
|
|
|
|
GLubyte* image=new GLubyte[256*256*3];
|
|
for(int y=0;y<256;++y)
|
|
{
|
|
const int t=y>>5;
|
|
GLubyte* pi=image+y*256*3;
|
|
for(int x=0;x<256;++x)
|
|
{
|
|
if (x<2||y<2||x>253||y>253)
|
|
{
|
|
pi[0]=0;
|
|
pi[1]=0;
|
|
pi[2]=0;
|
|
} else
|
|
{
|
|
pi[0]=255;
|
|
pi[1]=255;
|
|
pi[2]=255;
|
|
}
|
|
|
|
/*
|
|
const int s=x>>5;
|
|
const GLubyte b=180;
|
|
GLubyte c=b+((s+t&1)&1)*(255-b);
|
|
pi[0]=c;
|
|
pi[1]=c;
|
|
pi[2]=c;
|
|
*/
|
|
|
|
pi+=3;
|
|
}
|
|
}
|
|
|
|
glGenTextures(1,(GLuint*)&m_texturehandle);
|
|
glBindTexture(GL_TEXTURE_2D,m_texturehandle);
|
|
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
|
|
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
|
|
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
|
|
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
|
|
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
|
|
gluBuild2DMipmaps(GL_TEXTURE_2D,3,256,256,GL_RGB,GL_UNSIGNED_BYTE,image);
|
|
delete[] image;
|
|
m_textureinitialized=true;
|
|
}
|
|
// glMatrixMode(GL_TEXTURE);
|
|
// glLoadIdentity();
|
|
// glMatrixMode(GL_MODELVIEW);
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
|
glBindTexture(GL_TEXTURE_2D,m_texturehandle);
|
|
|
|
} else
|
|
{
|
|
glDisable(GL_TEXTURE_2D);
|
|
}
|
|
|
|
glEnable(GL_COLOR_MATERIAL);
|
|
|
|
err = glGetError();
|
|
assert(err==GL_NO_ERROR);
|
|
|
|
// glEnable(GL_CULL_FACE);
|
|
// glCullFace(GL_BACK);
|
|
}
|
|
|
|
void updateCamera()
|
|
{
|
|
|
|
|
|
|
|
btVector3 m_cameraUp(0,1,0);
|
|
int m_forwardAxis=2;
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
|
|
|
|
//m_azi+=0.0f;
|
|
|
|
btScalar rele = m_ele * btScalar(0.01745329251994329547);// rads per deg
|
|
btScalar razi = m_azi * btScalar(0.01745329251994329547);// rads per deg
|
|
|
|
|
|
btQuaternion rot(m_cameraUp,razi);
|
|
|
|
|
|
btVector3 eyePos(0,0,0);
|
|
eyePos[m_forwardAxis] = -m_cameraDistance;
|
|
|
|
btVector3 forward(eyePos[0],eyePos[1],eyePos[2]);
|
|
if (forward.length2() < SIMD_EPSILON)
|
|
{
|
|
forward.setValue(1.f,0.f,0.f);
|
|
}
|
|
btVector3 right = m_cameraUp.cross(forward);
|
|
btQuaternion roll(right,-rele);
|
|
|
|
eyePos = btMatrix3x3(rot) * btMatrix3x3(roll) * eyePos;
|
|
|
|
m_cameraPosition[0] = eyePos.getX();
|
|
m_cameraPosition[1] = eyePos.getY();
|
|
m_cameraPosition[2] = eyePos.getZ();
|
|
m_cameraPosition += m_cameraTargetPosition;
|
|
|
|
|
|
float m_frustumZNear=1;
|
|
float m_frustumZFar=1000;
|
|
|
|
if (m_glutScreenWidth == 0 && m_glutScreenHeight == 0)
|
|
return;
|
|
|
|
float aspect;
|
|
btVector3 extents;
|
|
|
|
if (m_glutScreenWidth > m_glutScreenHeight)
|
|
{
|
|
aspect = m_glutScreenWidth / (float)m_glutScreenHeight;
|
|
extents.setValue(aspect * 1.0f, 1.0f,0);
|
|
} else
|
|
{
|
|
aspect = m_glutScreenHeight / (float)m_glutScreenWidth;
|
|
extents.setValue(1.0f, aspect*1.f,0);
|
|
}
|
|
|
|
|
|
if (m_ortho)
|
|
{
|
|
// reset matrix
|
|
glLoadIdentity();
|
|
extents *= m_cameraDistance;
|
|
btVector3 lower = m_cameraTargetPosition - extents;
|
|
btVector3 upper = m_cameraTargetPosition + extents;
|
|
glOrtho(lower.getX(), upper.getX(), lower.getY(), upper.getY(),-1000,1000);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glLoadIdentity();
|
|
} else
|
|
{
|
|
if (m_glutScreenWidth > m_glutScreenHeight)
|
|
{
|
|
glFrustum (-aspect * m_frustumZNear, aspect * m_frustumZNear, -m_frustumZNear, m_frustumZNear, m_frustumZNear, m_frustumZFar);
|
|
} else
|
|
{
|
|
glFrustum (-aspect * m_frustumZNear, aspect * m_frustumZNear, -m_frustumZNear, m_frustumZNear, m_frustumZNear, m_frustumZFar);
|
|
}
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glLoadIdentity();
|
|
gluLookAt(m_cameraPosition[0], m_cameraPosition[1], m_cameraPosition[2],
|
|
m_cameraTargetPosition[0], m_cameraTargetPosition[1], m_cameraTargetPosition[2],
|
|
m_cameraUp.getX(),m_cameraUp.getY(),m_cameraUp.getZ());
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void GLInstancingRenderer::RenderScene(void)
|
|
{
|
|
BT_PROFILE("GlutDisplayFunc");
|
|
|
|
myinit();
|
|
|
|
updateCamera();
|
|
|
|
//render coordinate system
|
|
glBegin(GL_LINES);
|
|
glColor3f(1,0,0);
|
|
glVertex3f(0,0,0);
|
|
glVertex3f(1,0,0);
|
|
glColor3f(0,1,0);
|
|
glVertex3f(0,0,0);
|
|
glVertex3f(0,1,0);
|
|
glColor3f(0,0,1);
|
|
glVertex3f(0,0,0);
|
|
glVertex3f(0,0,1);
|
|
glEnd();
|
|
|
|
//do a finish, to make sure timings are clean
|
|
// glFinish();
|
|
|
|
|
|
|
|
// glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
glBindBuffer(GL_ARRAY_BUFFER, cube_vbo);
|
|
glFlush();
|
|
|
|
//updatePos();
|
|
|
|
// simulationLoop();
|
|
|
|
//useCPU = true;
|
|
|
|
int totalNumInstances = 0;
|
|
|
|
for (int i=0;i<m_graphicsInstances.size();i++)
|
|
{
|
|
totalNumInstances+=m_graphicsInstances[i]->m_numGraphicsInstances;
|
|
}
|
|
|
|
int curOffset = 0;
|
|
|
|
for (int i=0;i<m_graphicsInstances.size();i++)
|
|
{
|
|
|
|
btGraphicsInstance* gfxObj = m_graphicsInstances[i];
|
|
int myOffset = gfxObj->m_instanceOffset*4*sizeof(float);
|
|
|
|
int POSITION_BUFFER_SIZE = (totalNumInstances*sizeof(float)*4);
|
|
int ORIENTATION_BUFFER_SIZE = (totalNumInstances*sizeof(float)*4);
|
|
int COLOR_BUFFER_SIZE = (totalNumInstances*sizeof(float)*4);
|
|
int SCALE_BUFFER_SIZE = (totalNumInstances*sizeof(float)*3);
|
|
|
|
glBindVertexArray(gfxObj->m_cube_vao);
|
|
|
|
|
|
int vertexStride = 9*sizeof(float);
|
|
int vertexBase = gfxObj->m_vertexArrayOffset*vertexStride;
|
|
|
|
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 9*sizeof(float), (GLvoid*)vertexBase);
|
|
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(curOffset*4*sizeof(float)+SHAPE_BUFFER_SIZE));
|
|
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(curOffset*4*sizeof(float)+SHAPE_BUFFER_SIZE+POSITION_BUFFER_SIZE));
|
|
int uvoffset = 7*sizeof(float)+vertexBase;
|
|
int normaloffset = 4*sizeof(float)+vertexBase;
|
|
|
|
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 9*sizeof(float), (GLvoid *)uvoffset);
|
|
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 9*sizeof(float), (GLvoid *)normaloffset);
|
|
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(curOffset*4*sizeof(float)+SHAPE_BUFFER_SIZE+POSITION_BUFFER_SIZE+ORIENTATION_BUFFER_SIZE));
|
|
glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid *)(curOffset*3*sizeof(float)+SHAPE_BUFFER_SIZE+POSITION_BUFFER_SIZE+ORIENTATION_BUFFER_SIZE+COLOR_BUFFER_SIZE));
|
|
|
|
glEnableVertexAttribArray(0);
|
|
glEnableVertexAttribArray(1);
|
|
glEnableVertexAttribArray(2);
|
|
glEnableVertexAttribArray(3);
|
|
glEnableVertexAttribArray(4);
|
|
glEnableVertexAttribArray(5);
|
|
glEnableVertexAttribArray(6);
|
|
|
|
glVertexAttribDivisor(0, 0);
|
|
glVertexAttribDivisor(1, 1);
|
|
glVertexAttribDivisor(2, 1);
|
|
glVertexAttribDivisor(3, 0);
|
|
glVertexAttribDivisor(4, 0);
|
|
glVertexAttribDivisor(5, 1);
|
|
glVertexAttribDivisor(6, 1);
|
|
|
|
glUseProgram(instancingShader);
|
|
glUniform1f(angle_loc, 0);
|
|
GLfloat pm[16];
|
|
glGetFloatv(GL_PROJECTION_MATRIX, pm);
|
|
glUniformMatrix4fv(ProjectionMatrix, 1, false, &pm[0]);
|
|
|
|
GLfloat mvm[16];
|
|
glGetFloatv(GL_MODELVIEW_MATRIX, mvm);
|
|
glUniformMatrix4fv(ModelViewMatrix, 1, false, &mvm[0]);
|
|
|
|
glUniform1i(uniform_texture_diffuse, 0);
|
|
|
|
glFlush();
|
|
|
|
if (gfxObj->m_numGraphicsInstances)
|
|
{
|
|
int indexCount = gfxObj->m_numIndices;
|
|
int indexOffset = 0;
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gfxObj->m_index_vbo);
|
|
{
|
|
BT_PROFILE("glDrawElementsInstanced");
|
|
glDrawElementsInstanced(GL_TRIANGLES, indexCount, GL_UNSIGNED_INT, (void*)indexOffset, gfxObj->m_numGraphicsInstances);
|
|
}
|
|
}
|
|
curOffset+= gfxObj->m_numGraphicsInstances;
|
|
}
|
|
glUseProgram(0);
|
|
glBindBuffer(GL_ARRAY_BUFFER,0);
|
|
glBindVertexArray(0);
|
|
|
|
|
|
GLint err = glGetError();
|
|
assert(err==GL_NO_ERROR);
|
|
}
|
|
|
|
|
|
void GLInstancingRenderer::CleanupShaders()
|
|
{
|
|
|
|
delete []m_data->m_instance_positions_ptr;
|
|
delete []m_data->m_instance_quaternion_ptr;
|
|
delete []m_data->m_instance_colors_ptr;
|
|
delete []m_data->m_instance_scale_ptr;
|
|
} |