From a3559b3c920a69ed29b4dbcee89821c35b325b47 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Sat, 25 May 2013 01:45:43 -0700 Subject: [PATCH] add preliminary ray tracing test (ray-sphere placeholder on CPU) --- Demos3/GpuDemos/GpuDemo.h | 9 +- Demos3/GpuDemos/main_opengl3core.cpp | 4 +- Demos3/GpuDemos/rigidbody/GpuConvexScene.cpp | 210 ++++++++++++++++++- Demos3/GpuDemos/rigidbody/GpuConvexScene.h | 30 ++- btgui/OpenGLWindow/GLPrimitiveRenderer.cpp | 21 +- btgui/OpenGLWindow/GLPrimitiveRenderer.h | 2 +- 6 files changed, 261 insertions(+), 15 deletions(-) diff --git a/Demos3/GpuDemos/GpuDemo.h b/Demos3/GpuDemos/GpuDemo.h index 84a283abb..81e74e20f 100644 --- a/Demos3/GpuDemos/GpuDemo.h +++ b/Demos3/GpuDemos/GpuDemo.h @@ -1,6 +1,7 @@ #ifndef GPU_DEMO_H #define GPU_DEMO_H class GLInstancingRenderer; +class GLPrimitiveRenderer; @@ -31,6 +32,8 @@ public: float gapY; float gapZ; GLInstancingRenderer* m_instancingRenderer; + GLPrimitiveRenderer* m_primRenderer; + class b3gWindowInterface* m_window; class GwenUserInterface* m_gui; @@ -38,9 +41,9 @@ public: :useOpenCL(true), preferredOpenCLPlatformIndex(-1), preferredOpenCLDeviceIndex(-1), - arraySizeX(30), - arraySizeY(30), - arraySizeZ(30), + arraySizeX(2), + arraySizeY(2), + arraySizeZ(2), m_useConcaveMesh(false), gapX(14.3), gapY(14.0), diff --git a/Demos3/GpuDemos/main_opengl3core.cpp b/Demos3/GpuDemos/main_opengl3core.cpp index f08a7eb7c..958226d3f 100644 --- a/Demos3/GpuDemos/main_opengl3core.cpp +++ b/Demos3/GpuDemos/main_opengl3core.cpp @@ -76,6 +76,8 @@ GpuDemo::CreateFunc* allDemos[]= // GpuConvexScene::MyCreateFunc, //ConcaveSphereScene::MyCreateFunc, + GpuRaytraceScene::MyCreateFunc, + GpuBoxPlaneScene::MyCreateFunc, GpuConvexPlaneScene::MyCreateFunc, @@ -601,7 +603,7 @@ int main(int argc, char* argv[]) ci.m_gui = gui; ci.m_instancingRenderer->init(); ci.m_instancingRenderer->InitShaders(); - + ci.m_primRenderer = &prim; // render.init(); demo->initPhysics(ci); diff --git a/Demos3/GpuDemos/rigidbody/GpuConvexScene.cpp b/Demos3/GpuDemos/rigidbody/GpuConvexScene.cpp index 9835391af..0dce134cd 100644 --- a/Demos3/GpuDemos/rigidbody/GpuConvexScene.cpp +++ b/Demos3/GpuDemos/rigidbody/GpuConvexScene.cpp @@ -18,9 +18,11 @@ #include "GpuRigidBodyDemoInternalData.h" #include "../gwenUserInterface.h" #include "Bullet3Dynamics/ConstraintSolver/b3Point2PointConstraint.h" +#include "OpenGLWindow/GLPrimitiveRenderer.h" void GpuConvexScene::setupScene(const ConstructionInfo& ci) { + m_primRenderer = ci.m_primRenderer; int index=0; createStaticEnvironment(ci); @@ -30,11 +32,15 @@ void GpuConvexScene::setupScene(const ConstructionInfo& ci) m_data->m_rigidBodyPipeline->writeAllInstancesToGpu(); - float camPos[4]={ci.arraySizeX,ci.arraySizeY/2,ci.arraySizeZ,0}; + float camPos[4]={0,0,0,0};//ci.arraySizeX,ci.arraySizeY/2,ci.arraySizeZ,0}; //float camPos[4]={1,12.5,1.5,0}; + m_instancingRenderer->setCameraTargetPosition(camPos); - m_instancingRenderer->setCameraDistance(100); + m_instancingRenderer->setCameraDistance(30); + m_instancingRenderer->setCameraYaw(0); + m_instancingRenderer->setCameraPitch(0); + m_instancingRenderer->updateCamera(); char msg[1024]; int numInstances = index; @@ -174,3 +180,203 @@ void GpuConvexPlaneScene::createStaticEnvironment(const ConstructionInfo& ci) int pid = m_data->m_rigidBodyPipeline->registerPhysicsInstance(0.f,position,orn,colIndex,index,false); } + +struct GpuRaytraceInternalData +{ + GLuint* m_texId; + unsigned char* m_texels; + int textureWidth; + int textureHeight; +}; +#include + +GpuRaytraceScene::GpuRaytraceScene() +{ + + m_raytraceData = new GpuRaytraceInternalData; + + m_raytraceData->m_texId = new GLuint; + m_raytraceData->textureWidth = 1024; + m_raytraceData->textureHeight = 768; + + //create new texture + glGenTextures(1, m_raytraceData->m_texId); + GLenum err = glGetError(); + assert(err==GL_NO_ERROR); + + + + glBindTexture(GL_TEXTURE_2D, *m_raytraceData->m_texId); + m_raytraceData->m_texels = (unsigned char*)malloc(m_raytraceData->textureWidth*m_raytraceData->textureHeight*3); + memset(m_raytraceData->m_texels,0,m_raytraceData->textureWidth*m_raytraceData->textureHeight*3); + for (int i=0;itextureWidth;i++) + { + for (int y=0;ytextureHeight;y++) + { + int color = 0; + if (ytextureHeight-1 && (y>0) && (i>0 && itextureWidth-1)) + color = 255; + + m_raytraceData->m_texels[(i+m_raytraceData->textureWidth*y)*3+0] = color; + m_raytraceData->m_texels[(i+m_raytraceData->textureWidth*y)*3+1] = color; + m_raytraceData->m_texels[(i+m_raytraceData->textureWidth*y)*3+2] = color; + } + } + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_raytraceData->textureWidth, m_raytraceData->textureHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, m_raytraceData->m_texels); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + err = glGetError(); + assert(err==GL_NO_ERROR); + +} +GpuRaytraceScene::~GpuRaytraceScene() +{ + glDeleteTextures(1,m_raytraceData->m_texId); + delete[] m_raytraceData->m_texels; + delete m_raytraceData; +} + + +bool sphere_intersect(const b3Vector3& spherePos, b3Scalar radius, const b3Vector3& rayFrom, const b3Vector3& rayTo) +{ + // rs = ray.org - sphere.center + const b3Vector3& rs = rayFrom - spherePos; + b3Vector3 rayDir = rayTo-rayFrom;//rayFrom-rayTo; + rayDir.normalize(); + + float B = b3Dot(rs, rayDir); + float C = b3Dot(rs, rs) - (radius * radius); + float D = B * B - C; + + if (D > 0.0) + { + float t = -B - sqrt(D); + if ( (t > 0.0))// && (t < isect.t) ) + { + return true;//isect.t = t; + } + } + return false; +} + +void GpuRaytraceScene::renderScene() +{ + B3_PROFILE("raytrace"); + //raytrace into the texels + m_instancingRenderer->updateCamera(); + //generate primary rays + + float top = 1.f; + float bottom = -1.f; + float nearPlane = 1.f; + + float tanFov = (top-bottom)*0.5f / nearPlane; + + float fov = 2.0 * atanf (tanFov); + + b3Vector3 rayFrom, camTarget; + m_instancingRenderer->getCameraPosition(rayFrom); + m_instancingRenderer->getCameraTargetPosition(camTarget); + b3Vector3 rayForward = camTarget-rayFrom; + rayForward.normalize(); + float farPlane = 500.f; + rayForward*= farPlane; + + b3Vector3 rightOffset; + b3Vector3 vertical(0.f,1.f,0.f); + b3Vector3 hor; + hor = rayForward.cross(vertical); + hor.normalize(); + vertical = hor.cross(rayForward); + vertical.normalize(); + + float tanfov = tanf(0.5f*fov); + + hor *= 2.f * farPlane * tanfov; + vertical *= 2.f * farPlane * tanfov; + + b3Vector3 rayToCenter = rayFrom + rayForward; + + //should be screenwidth/height + b3Vector3 dHor = hor * 1.f/float(m_raytraceData->textureWidth); + b3Vector3 dVert = vertical * 1.f/float(m_raytraceData->textureHeight); + + b3Transform rayFromTrans; + rayFromTrans.setIdentity(); + rayFromTrans.setOrigin(rayFrom); + + b3Transform rayFromLocal; + b3Transform rayToLocal; + + + + //cast primary rays + + m_data->m_np->readbackAllBodiesToCpu(); + + for (int x=0;xtextureWidth;x++) + { + for (int y=0;ytextureHeight;y++) + { + + b3Vector3 rayTo = rayToCenter - 0.5f * hor + 0.5f * vertical; + rayTo += x * dHor; + rayTo -= y * dVert; + + //if there is a hit, color the pixels + int numBodies = m_data->m_rigidBodyPipeline->getNumBodies(); + bool hits = false; + + for (int i=0;im_np->getObjectTransformFromCpu(pos,orn,i); + b3Scalar radius = 1; + + hits = sphere_intersect(pos, radius, rayFrom, rayTo); + } + + if (hits) + { + m_raytraceData->m_texels[(x+m_raytraceData->textureWidth*y)*3+0] = 255; + m_raytraceData->m_texels[(x+m_raytraceData->textureWidth*y)*3+1] = 0; + m_raytraceData->m_texels[(x+m_raytraceData->textureWidth*y)*3+2] = 0; + } else + { + m_raytraceData->m_texels[(x+m_raytraceData->textureWidth*y)*3+0] = 0; + m_raytraceData->m_texels[(x+m_raytraceData->textureWidth*y)*3+1] = 0; + m_raytraceData->m_texels[(x+m_raytraceData->textureWidth*y)*3+2] = 0; + } + + + + + } + } + + + + GLint err; + + err = glGetError(); + assert(err==GL_NO_ERROR); + glActiveTexture(GL_TEXTURE0); + + glBindTexture(GL_TEXTURE_2D, *m_raytraceData->m_texId); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_raytraceData->textureWidth, m_raytraceData->textureHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, m_raytraceData->m_texels); + + err = glGetError(); + assert(err==GL_NO_ERROR); + b3Assert(m_primRenderer); + float color[4] = {1,1,1,1}; + float rect[4] = {0,0,m_raytraceData->textureWidth,m_raytraceData->textureHeight}; + float u[2] = {0,1}; + float v[2] = {0,1}; + int useRGBA = 1; + m_primRenderer->drawTexturedRect(rect[0],rect[1],rect[2],rect[3],color,u[0],v[0],u[1],v[1], useRGBA); + err = glGetError(); + assert(err==GL_NO_ERROR); +} diff --git a/Demos3/GpuDemos/rigidbody/GpuConvexScene.h b/Demos3/GpuDemos/rigidbody/GpuConvexScene.h index 368c03b3d..3bf1239c0 100644 --- a/Demos3/GpuDemos/rigidbody/GpuConvexScene.h +++ b/Demos3/GpuDemos/rigidbody/GpuConvexScene.h @@ -5,9 +5,12 @@ class GpuConvexScene : public GpuRigidBodyDemo { +protected: + class GLPrimitiveRenderer* m_primRenderer; + public: - GpuConvexScene(){} + GpuConvexScene() :m_primRenderer(0) {} virtual ~GpuConvexScene(){} virtual const char* getName() { @@ -72,7 +75,30 @@ public: virtual int createDynamicsObjects(const ConstructionInfo& ci); - }; + +class GpuRaytraceScene : public GpuBoxPlaneScene +{ +protected: + struct GpuRaytraceInternalData* m_raytraceData; + +public: + GpuRaytraceScene(); + virtual ~GpuRaytraceScene(); + virtual const char* getName() + { + return "GPURaytrace"; + } + + static GpuDemo* MyCreateFunc() + { + GpuDemo* demo = new GpuRaytraceScene; + return demo; + } + + void renderScene(); +}; + + #endif //GPU_CONVEX_SCENE_H diff --git a/btgui/OpenGLWindow/GLPrimitiveRenderer.cpp b/btgui/OpenGLWindow/GLPrimitiveRenderer.cpp index dfbe9c090..e1feff344 100644 --- a/btgui/OpenGLWindow/GLPrimitiveRenderer.cpp +++ b/btgui/OpenGLWindow/GLPrimitiveRenderer.cpp @@ -9,7 +9,6 @@ static const char* vertexShader= \ "#version 150 \n" "\n" -"uniform vec2 p;\n" "\n" "in vec4 position;\n" "in vec4 colour;\n" @@ -22,13 +21,14 @@ static const char* vertexShader= \ "void main (void)\n" "{\n" " colourV = colour;\n" -" gl_Position = vec4(p.x+position.x, p.y+position.y,0.f,1.f);\n" +" gl_Position = vec4(position.x, position.y,0.f,1.f);\n" " texuvV=texuv;\n" "}\n"; static const char* fragmentShader= \ "#version 150\n" "\n" +"uniform vec2 p;\n" "in vec4 colourV;\n" "out vec4 fragColour;\n" "in vec2 texuvV;\n" @@ -37,9 +37,11 @@ static const char* fragmentShader= \ "\n" "void main(void)\n" "{\n" -" vec4 texcolorred = texture(Diffuse,texuvV);\n" -"// vec4 texcolor = vec4(texcolorred.x,texcolorred.x,texcolorred.x,1);\n" -" vec4 texcolor = vec4(1,1,1,texcolorred.x);\n" +" vec4 texcolor = texture(Diffuse,texuvV);\n" +" if (p.x==0.f)\n" +" {\n" +" texcolor = vec4(1,1,1,texcolor.x);\n" +" }\n" "\n" " fragColour = colourV*texcolor;\n" "}\n"; @@ -89,6 +91,7 @@ m_screenHeight(screenHeight) m_data = new PrimInternalData; m_data->m_shaderProg = gltLoadShaderPair(vertexShader,fragmentShader); + m_data->m_positionUniform = glGetUniformLocation(m_data->m_shaderProg, "p"); if (m_data->m_positionUniform < 0) { @@ -231,7 +234,7 @@ void GLPrimitiveRenderer::drawRect(float x0, float y0, float x1, float y1, float } -void GLPrimitiveRenderer::drawTexturedRect(float x0, float y0, float x1, float y1, float color[4], float u0,float v0, float u1, float v1)//Line()//float from[4], float to[4], float color[4]) +void GLPrimitiveRenderer::drawTexturedRect(float x0, float y0, float x1, float y1, float color[4], float u0,float v0, float u1, float v1, int useRGBA) { GLint err; @@ -276,6 +279,12 @@ void GLPrimitiveRenderer::drawTexturedRect(float x0, float y0, float x1, float y assert(err==GL_NO_ERROR); vec2 p( 0.f,0.f);//?b?0.5f * sinf(timeValue), 0.5f * cosf(timeValue) ); + if (useRGBA) + { + p.p[0] = 1.f; + p.p[1] = 1.f; + } + glUniform2fv(m_data->m_positionUniform, 1, (const GLfloat *)&p); err = glGetError(); diff --git a/btgui/OpenGLWindow/GLPrimitiveRenderer.h b/btgui/OpenGLWindow/GLPrimitiveRenderer.h index b88c33b1c..1aef1d06b 100644 --- a/btgui/OpenGLWindow/GLPrimitiveRenderer.h +++ b/btgui/OpenGLWindow/GLPrimitiveRenderer.h @@ -18,7 +18,7 @@ public: virtual ~GLPrimitiveRenderer(); void drawRect(float x0, float y0, float x1, float y1, float color[4]); - void drawTexturedRect(float x0, float y0, float x1, float y1, float color[4], float u0,float v0, float u1, float v1); + void drawTexturedRect(float x0, float y0, float x1, float y1, float color[4], float u0,float v0, float u1, float v1, int useRGBA=0); void drawLine();//float from[4], float to[4], float color[4]); void setScreenSize(int width, int height);