From 03bdcc87379c9d72f7341df8f4d0a46cd8df8b85 Mon Sep 17 00:00:00 2001 From: erwin coumans Date: Tue, 26 Apr 2016 20:52:52 -0700 Subject: [PATCH] patch TinyRenderer so it software-renders in an OpenGL texture, for testing fix texture support: flip texture to make OpenGL happy (lower-left is origin) add path prefix to .obj loader, so materials/textures are loaded ok. --- build3/premake4.lua | 1 + data/floor.mtl | 13 + data/floor.obj | 18 ++ data/floor_diffuse.jpg | Bin 0 -> 29586 bytes data/floor_diffuse.tga | Bin 0 -> 34436 bytes data/floor_nm_tangent.tga | Bin 0 -> 8236 bytes .../ImportObjDemo/ImportObjExample.cpp | 2 +- .../OpenGLWindow/GLInstancingRenderer.cpp | 29 +- examples/TinyRenderer/Makefile | 23 -- examples/TinyRenderer/README.md | 55 ---- examples/TinyRenderer/TinyRenderer.cpp | 172 +++++++++++ examples/TinyRenderer/TinyRenderer.h | 39 +++ examples/TinyRenderer/geometry.h | 11 +- examples/TinyRenderer/main.cpp | 289 ++++++++++++------ examples/TinyRenderer/our_gl.cpp | 27 +- examples/TinyRenderer/our_gl.h | 12 +- 16 files changed, 496 insertions(+), 195 deletions(-) create mode 100644 data/floor.mtl create mode 100644 data/floor.obj create mode 100644 data/floor_diffuse.jpg create mode 100644 data/floor_diffuse.tga create mode 100644 data/floor_nm_tangent.tga delete mode 100644 examples/TinyRenderer/Makefile delete mode 100644 examples/TinyRenderer/README.md create mode 100644 examples/TinyRenderer/TinyRenderer.cpp create mode 100644 examples/TinyRenderer/TinyRenderer.h diff --git a/build3/premake4.lua b/build3/premake4.lua index 7f60a1d0e..108f33473 100644 --- a/build3/premake4.lua +++ b/build3/premake4.lua @@ -181,6 +181,7 @@ include "../examples/OpenGLWindow" include "../examples/ThirdPartyLibs/Gwen" include "../examples/SimpleOpenGL3" + include "../examples/TinyRenderer" include "../examples/HelloWorld" include "../examples/BasicDemo" diff --git a/data/floor.mtl b/data/floor.mtl new file mode 100644 index 000000000..966cc66cc --- /dev/null +++ b/data/floor.mtl @@ -0,0 +1,13 @@ +newmtl floor + Ns 10.0000 + Ni 1.5000 + d 1.0000 + Tr 0.0000 + Tf 1.0000 1.0000 1.0000 + illum 2 + Ka 0.0000 0.0000 0.0000 + Kd 0.5880 0.5880 0.5880 + Ks 0.0000 0.0000 0.0000 + Ke 0.0000 0.0000 0.0000 + map_Ka floor_diffuse.jpg + map_Kd cube.tga diff --git a/data/floor.obj b/data/floor.obj new file mode 100644 index 000000000..176c05363 --- /dev/null +++ b/data/floor.obj @@ -0,0 +1,18 @@ +o +mtllib floor.mtl +v -1 -1 -1 +v 1 -1 -1 +v 1 -1 1 +v -1 -1 1 + +vt 0 0 +vt .25 0 +vt .25 .25 +vt 0 .25 + +vn 0 1 0 +usemtl floor + +f 3/3/1 2/2/1 1/1/1 +f 4/4/1 3/3/1 1/1/1 + diff --git a/data/floor_diffuse.jpg b/data/floor_diffuse.jpg new file mode 100644 index 0000000000000000000000000000000000000000..36a26252dfc8b040d9ec4e716f6f6299a63f702f GIT binary patch literal 29586 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 literal 0 HcmV?d00001 diff --git a/data/floor_nm_tangent.tga b/data/floor_nm_tangent.tga new file mode 100644 index 0000000000000000000000000000000000000000..3b8474e8f3bde3ba8d48cafd553358f90d39bcdb GIT binary patch literal 8236 zcmeI&%L#xm6a>IWj#gk3+C_wbDEPx}Qn~0!dk|(}8(8MJ5lwtak=nSgTGa*&Fu(u< z3^2d|0}L?000Rs#zyJdbFu(u<3^2d|0}L?000RvC+raw<*p@vXWi9j6okJOO9}kiv B)@uL& literal 0 HcmV?d00001 diff --git a/examples/Importers/ImportObjDemo/ImportObjExample.cpp b/examples/Importers/ImportObjDemo/ImportObjExample.cpp index db6ef97e0..26b0e95e8 100644 --- a/examples/Importers/ImportObjDemo/ImportObjExample.cpp +++ b/examples/Importers/ImportObjDemo/ImportObjExample.cpp @@ -101,7 +101,7 @@ void ImportObjSetup::initPhysics() const char* filename = shape.material.diffuse_texname.c_str(); const unsigned char* image=0; - const char* prefix[]={"./","./data/","../data/","../../data/","../../../data/","../../../../data/"}; + const char* prefix[]={ pathPrefix,"./","./data/","../data/","../../data/","../../../data/","../../../../data/"}; int numprefix = sizeof(prefix)/sizeof(const char*); for (int i=0;!image && im_textureHandles.push_back(h); + updateTexture(textureIndex, texels); return textureIndex; } @@ -552,13 +547,31 @@ void GLInstancingRenderer::updateTexture(int textureIndex, const unsigned cha { if (textureIndex>=0) { + + + glActiveTexture(GL_TEXTURE0); b3Assert(glGetError() ==GL_NO_ERROR); InternalTextureHandle& h = m_data->m_textureHandles[textureIndex]; + + //textures need to be flipped for OpenGL... + b3AlignedObjectArray flippedTexels; + flippedTexels.resize(h.m_width* h.m_height * 3); + for (int i = 0; i < h.m_width; i++) + { + for (int j = 0; j < h.m_height; j++) + { + flippedTexels[(i + j*h.m_width) * 3] = texels[(i + (h.m_height-1-j)*h.m_width) * 3]; + flippedTexels[(i + j*h.m_width) * 3+1] = texels[(i + (h.m_height - 1 - j)*h.m_width) * 3+1]; + flippedTexels[(i + j*h.m_width) * 3+2] = texels[(i + (h.m_height - 1 - j)*h.m_width) * 3+1]; + } + } + + glBindTexture(GL_TEXTURE_2D,h.m_glTexture); b3Assert(glGetError() ==GL_NO_ERROR); const GLubyte* image= (const GLubyte*)texels; - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, h.m_width,h.m_height,0,GL_RGB,GL_UNSIGNED_BYTE,image); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, h.m_width,h.m_height,0,GL_RGB,GL_UNSIGNED_BYTE,&flippedTexels[0]); b3Assert(glGetError() ==GL_NO_ERROR); glGenerateMipmap(GL_TEXTURE_2D); b3Assert(glGetError() ==GL_NO_ERROR); diff --git a/examples/TinyRenderer/Makefile b/examples/TinyRenderer/Makefile deleted file mode 100644 index 0b0a469b0..000000000 --- a/examples/TinyRenderer/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -SYSCONF_LINK = g++ -CPPFLAGS = -Wall -Wextra -Weffc++ -pedantic -std=c++98 -LDFLAGS = -O3 -LIBS = -lm - -DESTDIR = ./ -TARGET = main - -OBJECTS := $(patsubst %.cpp,%.o,$(wildcard *.cpp)) - -all: $(DESTDIR)$(TARGET) - -$(DESTDIR)$(TARGET): $(OBJECTS) - $(SYSCONF_LINK) -Wall $(LDFLAGS) -o $(DESTDIR)$(TARGET) $(OBJECTS) $(LIBS) - -$(OBJECTS): %.o: %.cpp - $(SYSCONF_LINK) -Wall $(CPPFLAGS) -c $(CFLAGS) $< -o $@ - -clean: - -rm -f $(OBJECTS) - -rm -f $(TARGET) - -rm -f *.tga - diff --git a/examples/TinyRenderer/README.md b/examples/TinyRenderer/README.md deleted file mode 100644 index 84a125234..000000000 --- a/examples/TinyRenderer/README.md +++ /dev/null @@ -1,55 +0,0 @@ -# Tiny Renderer or how OpenGL works: software renderer in 500 lines of code - -*** - -**Check [the wiki](https://github.com/ssloy/tinyrenderer/wiki/Lesson-1:-Bresenham%E2%80%99s-Line-Drawing-Algorithm) for the detailed lessons. My source code is irrelevant. Read the wiki and implement your own renderer. Only when you suffer through all the tiny details you will learn what is going on.** - -**I do want to get emails for feedback (dmitry.sokolov@univ-lorraine.fr); do not hesitate to contact me if you have any questions.** - -**If you are a teacher and willing to adopt this material for teaching your class your are very welcome, no authorization is needed, simply inform me by mail, it will help me to improve the course.** - -*** - -In this series of articles, I want to show the way OpenGL works by writing its clone (a much simplified one). Surprisingly enough, I often meet people who cannot overcome the initial hurdle of learning OpenGL / DirectX. Thus, I have prepared a short series of lectures, after which my students show quite good renderers. - -So, the task is formulated as follows: using no third-party libraries (especially graphic ones), get something like this picture: - -![](http://haqr.eu/framebuffer.png) - -_Warning: this is a training material that will loosely repeat the structure of the OpenGL library. It will be a software renderer. **I do not want to show how to write applications for OpenGL. I want to show how OpenGL works.** I am deeply convinced that it is impossible to write efficient applications using 3D libraries without understanding this._ - -I will try to make the final code about 500 lines. My students need 10 to 20 programming hours to begin making such renderers. At the input, we get a test file with a polygonal wire + pictures with textures. At the output, we’ll get a rendered model. No graphical interface, the program simply generates an image. - - -Since the goal is to minimize external dependencies, I give my students just one class that allows working with [TGA](http://en.wikipedia.org/wiki/Truevision_TGA) files. It’s one of the simplest formats that supports images in RGB/RGBA/black and white formats. So, as a starting point, we’ll obtain a simple way to work with pictures. You should note that the only functionality available at the very beginning (in addition to loading and saving images) is the capability to set the color of one pixel. - -There are no functions for drawing line segments and triangles. We’ll have to do all of this by hand. I provide my source code that I write in parallel with students. But I would not recommend using it, as this doesn’t make sense. The entire code is available on github, and [here](https://github.com/ssloy/tinyrenderer/tree/909fe20934ba5334144d2c748805690a1fa4c89f) you will find the source code I give to my students. - -```C++ -#include "tgaimage.h" -const TGAColor white = TGAColor(255, 255, 255, 255); -const TGAColor red = TGAColor(255, 0, 0, 255); -int main(int argc, char** argv) { - TGAImage image(100, 100, TGAImage::RGB); - image.set(52, 41, red); - image.flip_vertically(); // i want to have the origin at the left bottom corner of the image - image.write_tga_file("output.tga");` - return 0; -} -``` - -output.tga should look something like this: - -![](http://www.loria.fr/~sokolovd/cg-course/img/2d3b12170b.png) - - - -# Teaser: few examples made with the renderer - -![](https://hsto.org/getpro/habr/post_images/50d/e2a/be9/50de2abe990efa345664f98c9464a4c8.png) - -![](https://hsto.org/getpro/habr/post_images/e3c/d70/492/e3cd704925f52b5466ab3c4f9fbab899.png) - -![](http://www.loria.fr/~sokolovd/cg-course/06-shaders/img/boggie.png) - -![](http://hsto.org/files/1ba/93f/a5a/1ba93fa5a48646e2a9614271c943b4da.png) diff --git a/examples/TinyRenderer/TinyRenderer.cpp b/examples/TinyRenderer/TinyRenderer.cpp new file mode 100644 index 000000000..3370c86fd --- /dev/null +++ b/examples/TinyRenderer/TinyRenderer.cpp @@ -0,0 +1,172 @@ +#include "TinyRenderer.h" + +#include +#include +#include +#include "TinyRenderer/tgaimage.h" +#include "TinyRenderer/model.h" +#include "TinyRenderer/geometry.h" +#include "TinyRenderer/our_gl.h" +#include "../../Utils/b3ResourcePath.h" +#include "Bullet3Common/b3MinMax.h" + +Vec3f light_dir_world(1,1,1); + + +struct Shader : public IShader { + + Model* m_model; + Vec3f m_light_dir_local; + Matrix& m_modelView; + Matrix& m_projectionMatrix; + + mat<2,3,float> varying_uv; // triangle uv coordinates, written by the vertex shader, read by the fragment shader + mat<4,3,float> varying_tri; // triangle coordinates (clip coordinates), written by VS, read by FS + mat<3,3,float> varying_nrm; // normal per vertex to be interpolated by FS + mat<3,3,float> ndc_tri; // triangle in normalized device coordinates + + Shader(Model* model, Vec3f light_dir_local, Matrix& modelView, Matrix& projectionMatrix) + :m_model(model), + m_light_dir_local(light_dir_local), + m_modelView(modelView), + m_projectionMatrix(projectionMatrix) + { + + } + + virtual Vec4f vertex(int iface, int nthvert) { + varying_uv.set_col(nthvert, m_model->uv(iface, nthvert)); + varying_nrm.set_col(nthvert, proj<3>((m_projectionMatrix*m_modelView).invert_transpose()*embed<4>(m_model->normal(iface, nthvert), 0.f))); + Vec4f gl_Vertex = m_projectionMatrix*m_modelView*embed<4>(m_model->vert(iface, nthvert)); + varying_tri.set_col(nthvert, gl_Vertex); + ndc_tri.set_col(nthvert, proj<3>(gl_Vertex/gl_Vertex[3])); + return gl_Vertex; + } + + virtual bool fragment(Vec3f bar, TGAColor &color) { + Vec3f bn = (varying_nrm*bar).normalize(); + Vec2f uv = varying_uv*bar; + + mat<3,3,float> A; + A[0] = ndc_tri.col(1) - ndc_tri.col(0); + A[1] = ndc_tri.col(2) - ndc_tri.col(0); + A[2] = bn; + + mat<3,3,float> AI = A.invert(); + + Vec3f i = AI * Vec3f(varying_uv[0][1] - varying_uv[0][0], varying_uv[0][2] - varying_uv[0][0], 0); + Vec3f j = AI * Vec3f(varying_uv[1][1] - varying_uv[1][0], varying_uv[1][2] - varying_uv[1][0], 0); + + mat<3,3,float> B; + B.set_col(0, i.normalize()); + B.set_col(1, j.normalize()); + B.set_col(2, bn); + + Vec3f n = (B*m_model->normal(uv)).normalize(); + + float diff = b3Min(b3Max(0.f, n*m_light_dir_local+0.6f),1.f); + color = m_model->diffuse(uv)*diff; + + return false; + } +}; + +/* +struct TinyRenderObjectData +{ + //Camera + Matrix m_viewMatrix; + Matrix m_projectionMatrix; + Matrix m_viewPortMatrix; + + //Model (vertices, indices, textures, shader) + Matrix m_modelMatrix; + class Model* m_model; + class IShader* m_shader; + + + //Output + TGAImage m_rgbColorBuffer; + b3AlignedObjectArray m_depthBuffer; +}; +*/ + +TinyRenderObjectData::TinyRenderObjectData(int width, int height, const char* fileName) +:m_width(width), +m_height(height), +m_rgbColorBuffer(width,height,TGAImage::RGB), +m_model(0) +{ + Vec3f eye(1,1,3); + Vec3f center(0,0,0); + Vec3f up(0,1,0); + + m_viewMatrix = lookat(eye, center, up); + m_viewportMatrix = viewport(width/8, height/8, width*3/4, height*3/4); + m_projectionMatrix = projection(-1.f/(eye-center).norm()); + + + m_depthBuffer.resize(width*height); + //todo(erwincoumans) move the file loading out of here + char relativeFileName[1024]; + if (!b3ResourcePath::findResourcePath(fileName, relativeFileName, 1024)) + { + printf("Cannot find file %s\n", fileName); + } else + { + m_model = new Model(relativeFileName); + } + + +} + +TinyRenderObjectData::~TinyRenderObjectData() +{ + delete m_model; +} + +void TinyRenderer::renderObject(TinyRenderObjectData& renderData) +{ + const char* fileName = "obj/floor.obj"; + + + +//new Model(relativeFileName);//argv[m]); + Model* model = renderData.m_model; + if (0==model) + return; + + const int width = renderData.m_width; + const int height = renderData.m_height; + b3AlignedObjectArray& zbuffer = renderData.m_depthBuffer; + + //todo(erwincoumans) make this a separate call + for (int i=width*height; i--; zbuffer[i] = -std::numeric_limits::max()); + + TGAImage& frame = renderData.m_rgbColorBuffer; + + //lookat(eye, center, up); + //viewport(width/8, height/8, width*3/4, height*3/4); + //projection(-1.f/(eye-center).norm()); + + Vec3f light_dir_local = proj<3>((renderData.m_projectionMatrix*renderData.m_viewMatrix*embed<4>(light_dir_world, 0.f))).normalize(); + + { + //for (int m=1; mnfaces(); i++) { + for (int j=0; j<3; j++) { + shader.vertex(i, j); + } + triangle(shader.varying_tri, shader, frame, &zbuffer[0], renderData.m_viewportMatrix); + } + + } + //frame.flip_vertically(); // to place the origin in the bottom left corner of the image + //frame.write_tga_file("framebuffer.tga"); + + +} + + diff --git a/examples/TinyRenderer/TinyRenderer.h b/examples/TinyRenderer/TinyRenderer.h new file mode 100644 index 000000000..1bcd49b95 --- /dev/null +++ b/examples/TinyRenderer/TinyRenderer.h @@ -0,0 +1,39 @@ +#ifndef TINY_RENDERER_H +#define TINY_RENDERER_H + +//#include "TinyRenderer/our_gl.h" +#include "TinyRenderer/geometry.h" +#include "Bullet3Common/b3AlignedObjectArray.h" +#include "TinyRenderer/tgaimage.h" + +struct TinyRenderObjectData +{ + //Camera + Matrix m_viewMatrix; + Matrix m_projectionMatrix; + Matrix m_viewportMatrix; + + //Model (vertices, indices, textures, shader) + Matrix m_modelMatrix; + class Model* m_model; + //class IShader* m_shader; todo(erwincoumans) expose the shader, for now we use a default shader + + //Output + int m_width; + int m_height; + TGAImage m_rgbColorBuffer; + b3AlignedObjectArray m_depthBuffer; + + TinyRenderObjectData(int width, int height, const char* objFileName); + virtual ~TinyRenderObjectData(); + +}; + + +class TinyRenderer +{ + public: + static void renderObject(TinyRenderObjectData& renderData); +}; + +#endif // TINY_RENDERER_Hbla diff --git a/examples/TinyRenderer/geometry.h b/examples/TinyRenderer/geometry.h index 46ee7b354..38bb4d935 100644 --- a/examples/TinyRenderer/geometry.h +++ b/examples/TinyRenderer/geometry.h @@ -1,9 +1,9 @@ #ifndef __GEOMETRY_H__ #define __GEOMETRY_H__ #include -#include #include -#include +#include + template class mat; @@ -85,14 +85,14 @@ template vec proj(const vec &v) template vec<3,T> cross(vec<3,T> v1, vec<3,T> v2) { return vec<3,T>(v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x); } - +#if 0 template std::ostream& operator<<(std::ostream& out, vec& v) { for(unsigned int i=0; i struct dt { @@ -204,11 +204,12 @@ templatemat operato return lhs; } +#if 0 template std::ostream& operator<<(std::ostream& out, mat& m) { for (size_t i=0; i Vec2f; diff --git a/examples/TinyRenderer/main.cpp b/examples/TinyRenderer/main.cpp index 8ce61dda2..7a9de8fef 100644 --- a/examples/TinyRenderer/main.cpp +++ b/examples/TinyRenderer/main.cpp @@ -1,94 +1,209 @@ -#include -#include -#include -#include "tgaimage.h" -#include "model.h" -#include "geometry.h" -#include "our_gl.h" +#include "OpenGLWindow/SimpleOpenGL3App.h" +#include "Bullet3Common/b3Quaternion.h" +#include "Bullet3Common/b3CommandLineArgs.h" +#include "assert.h" +#include -Model *model = NULL; +char* gVideoFileName = 0; +char* gPngFileName = 0; -const int width = 800; -const int height = 800; +static b3WheelCallback sOldWheelCB = 0; +static b3ResizeCallback sOldResizeCB = 0; +static b3MouseMoveCallback sOldMouseMoveCB = 0; +static b3MouseButtonCallback sOldMouseButtonCB = 0; +static b3KeyboardCallback sOldKeyboardCB = 0; +//static b3RenderCallback sOldRenderCB = 0; -Vec3f light_dir(1,1,1); -Vec3f eye(1,1,3); -Vec3f center(0,0,0); -Vec3f up(0,1,0); +float gWidth = 0 ; +float gHeight = 0; -struct Shader : public IShader { - mat<2,3,float> varying_uv; // triangle uv coordinates, written by the vertex shader, read by the fragment shader - mat<4,3,float> varying_tri; // triangle coordinates (clip coordinates), written by VS, read by FS - mat<3,3,float> varying_nrm; // normal per vertex to be interpolated by FS - mat<3,3,float> ndc_tri; // triangle in normalized device coordinates +void MyWheelCallback(float deltax, float deltay) +{ + if (sOldWheelCB) + sOldWheelCB(deltax,deltay); +} +void MyResizeCallback( float width, float height) +{ + gWidth = width; + gHeight = height; + + if (sOldResizeCB) + sOldResizeCB(width,height); +} +void MyMouseMoveCallback( float x, float y) +{ + printf("Mouse Move: %f, %f\n", x,y); - virtual Vec4f vertex(int iface, int nthvert) { - varying_uv.set_col(nthvert, model->uv(iface, nthvert)); - varying_nrm.set_col(nthvert, proj<3>((Projection*ModelView).invert_transpose()*embed<4>(model->normal(iface, nthvert), 0.f))); - Vec4f gl_Vertex = Projection*ModelView*embed<4>(model->vert(iface, nthvert)); - varying_tri.set_col(nthvert, gl_Vertex); - ndc_tri.set_col(nthvert, proj<3>(gl_Vertex/gl_Vertex[3])); - return gl_Vertex; - } - - virtual bool fragment(Vec3f bar, TGAColor &color) { - Vec3f bn = (varying_nrm*bar).normalize(); - Vec2f uv = varying_uv*bar; - - mat<3,3,float> A; - A[0] = ndc_tri.col(1) - ndc_tri.col(0); - A[1] = ndc_tri.col(2) - ndc_tri.col(0); - A[2] = bn; - - mat<3,3,float> AI = A.invert(); - - Vec3f i = AI * Vec3f(varying_uv[0][1] - varying_uv[0][0], varying_uv[0][2] - varying_uv[0][0], 0); - Vec3f j = AI * Vec3f(varying_uv[1][1] - varying_uv[1][0], varying_uv[1][2] - varying_uv[1][0], 0); - - mat<3,3,float> B; - B.set_col(0, i.normalize()); - B.set_col(1, j.normalize()); - B.set_col(2, bn); - - Vec3f n = (B*model->normal(uv)).normalize(); - - float diff = std::max(0.f, n*light_dir); - color = model->diffuse(uv)*diff; - - return false; - } -}; - -int main(int argc, char** argv) { - if (2>argc) { - std::cerr << "Usage: " << argv[0] << " obj/model.obj" << std::endl; - return 1; - } - - float *zbuffer = new float[width*height]; - for (int i=width*height; i--; zbuffer[i] = -std::numeric_limits::max()); - - TGAImage frame(width, height, TGAImage::RGB); - lookat(eye, center, up); - viewport(width/8, height/8, width*3/4, height*3/4); - projection(-1.f/(eye-center).norm()); - light_dir = proj<3>((Projection*ModelView*embed<4>(light_dir, 0.f))).normalize(); - - for (int m=1; mnfaces(); i++) { - for (int j=0; j<3; j++) { - shader.vertex(i, j); - } - triangle(shader.varying_tri, shader, frame, zbuffer); - } - delete model; - } - frame.flip_vertically(); // to place the origin in the bottom left corner of the image - frame.write_tga_file("framebuffer.tga"); - - delete [] zbuffer; - return 0; + if (sOldMouseMoveCB) + sOldMouseMoveCB(x,y); +} +void MyMouseButtonCallback(int button, int state, float x, float y) +{ + if (sOldMouseButtonCB) + sOldMouseButtonCB(button,state,x,y); } + +void MyKeyboardCallback(int keycode, int state) +{ + //keycodes are in examples/CommonInterfaces/CommonWindowInterface.h + //for example B3G_ESCAPE for escape key + //state == 1 for pressed, state == 0 for released. + // use app->m_window->isModifiedPressed(...) to check for shift, escape and alt keys + printf("MyKeyboardCallback received key:%c in state %d\n",keycode,state); + if (sOldKeyboardCB) + sOldKeyboardCB(keycode,state); +} +#include "TinyRenderer.h" + +int main(int argc, char* argv[]) +{ + b3CommandLineArgs myArgs(argc,argv); + + + + SimpleOpenGL3App* app = new SimpleOpenGL3App("SimpleOpenGL3App",640,480,true); + + app->m_instancingRenderer->getActiveCamera()->setCameraDistance(13); + app->m_instancingRenderer->getActiveCamera()->setCameraPitch(0); + app->m_instancingRenderer->getActiveCamera()->setCameraTargetPosition(0,0,0); + sOldKeyboardCB = app->m_window->getKeyboardCallback(); + app->m_window->setKeyboardCallback(MyKeyboardCallback); + sOldMouseMoveCB = app->m_window->getMouseMoveCallback(); + app->m_window->setMouseMoveCallback(MyMouseMoveCallback); + sOldMouseButtonCB = app->m_window->getMouseButtonCallback(); + app->m_window->setMouseButtonCallback(MyMouseButtonCallback); + sOldWheelCB = app->m_window->getWheelCallback(); + app->m_window->setWheelCallback(MyWheelCallback); + sOldResizeCB = app->m_window->getResizeCallback(); + app->m_window->setResizeCallback(MyResizeCallback); + + int textureWidth = gWidth; + int textureHeight = gHeight; + + TinyRenderObjectData renderData(textureWidth, textureHeight, "african_head/african_head.obj");//floor.obj"); + + + + myArgs.GetCmdLineArgument("mp4_file",gVideoFileName); + if (gVideoFileName) + app->dumpFramesToVideo(gVideoFileName); + + myArgs.GetCmdLineArgument("png_file",gPngFileName); + char fileName[1024]; + + + + unsigned char* image=new unsigned char[textureWidth*textureHeight*4]; + + + int textureHandle = app->m_renderer->registerTexture(image,textureWidth,textureHeight); + + int cubeIndex = app->registerCubeShape(1,1,1); + + b3Vector3 pos = b3MakeVector3(0,0,0); + b3Quaternion orn(0,0,0,1); + b3Vector3 color=b3MakeVector3(1,0,0); + b3Vector3 scaling=b3MakeVector3 (1,1,1); + app->m_renderer->registerGraphicsInstance(cubeIndex,pos,orn,color,scaling); + app->m_renderer->writeTransforms(); + + do + { + static int frameCount = 0; + frameCount++; + if (gPngFileName) + { + printf("gPngFileName=%s\n",gPngFileName); + + sprintf(fileName,"%s%d.png",gPngFileName,frameCount++); + app->dumpNextFrameToPng(fileName); + } + + app->m_instancingRenderer->init(); + app->m_instancingRenderer->updateCamera(); + + float projMat[16]; + app->m_instancingRenderer->getActiveCamera()->getCameraProjectionMatrix(projMat); + float viewMat[16]; + app->m_instancingRenderer->getActiveCamera()->getCameraViewMatrix(viewMat); + for (int i=0;i<4;i++) + { + for (int j=0;j<4;j++) + { + renderData.m_viewMatrix[i][j] = viewMat[i+4*j]; + //renderData.m_projectionMatrix[i][j] = projMat[i+4*j]; + } + } + + for(int y=0;y>4; + unsigned char* pi=image+y*textureWidth*3; + for(int x=0;x>4; + const unsigned char b=180; + unsigned char c=b+((s+(t&1))&1)*(255-b); + pi[0]=pi[1]=pi[2]=pi[3]=c;pi+=3; + } + } + #endif + + + app->m_renderer->activateTexture(textureHandle); + app->m_renderer->updateTexture(textureHandle,image); + + float color[4] = {1,1,1,1}; + app->m_primRenderer->drawTexturedRect(0,0,gWidth/3,gHeight/3,color,0,0,1,1,true); + + + + app->m_renderer->renderScene(); + app->drawGrid(); + char bla[1024]; + sprintf(bla,"Simple test frame %d", frameCount); + + app->drawText(bla,10,10); + app->swapBuffer(); + } while (!app->m_window->requestedExit()); + + + delete app; + return 0; +} diff --git a/examples/TinyRenderer/our_gl.cpp b/examples/TinyRenderer/our_gl.cpp index 3772c984a..4c99c0685 100644 --- a/examples/TinyRenderer/our_gl.cpp +++ b/examples/TinyRenderer/our_gl.cpp @@ -2,14 +2,16 @@ #include #include #include "our_gl.h" +#include "Bullet3Common/b3MinMax.h" + + -Matrix ModelView; -Matrix Viewport; -Matrix Projection; IShader::~IShader() {} -void viewport(int x, int y, int w, int h) { +Matrix viewport(int x, int y, int w, int h) +{ + Matrix Viewport; Viewport = Matrix::identity(); Viewport[0][3] = x+w/2.f; Viewport[1][3] = y+h/2.f; @@ -17,14 +19,17 @@ void viewport(int x, int y, int w, int h) { Viewport[0][0] = w/2.f; Viewport[1][1] = h/2.f; Viewport[2][2] = 0; + return Viewport; } -void projection(float coeff) { +Matrix projection(float coeff) { + Matrix Projection; Projection = Matrix::identity(); Projection[3][2] = coeff; + return Projection; } -void lookat(Vec3f eye, Vec3f center, Vec3f up) { +Matrix lookat(Vec3f eye, Vec3f center, Vec3f up) { Vec3f z = (eye-center).normalize(); Vec3f x = cross(up,z).normalize(); Vec3f y = cross(z,x).normalize(); @@ -36,7 +41,9 @@ void lookat(Vec3f eye, Vec3f center, Vec3f up) { Minv[2][i] = z[i]; Tr[i][3] = -center[i]; } + Matrix ModelView; ModelView = Minv*Tr; + return ModelView; } Vec3f barycentric(Vec2f A, Vec2f B, Vec2f C, Vec2f P) { @@ -52,8 +59,8 @@ Vec3f barycentric(Vec2f A, Vec2f B, Vec2f C, Vec2f P) { return Vec3f(-1,1,1); // in this case generate negative coordinates, it will be thrown away by the rasterizator } -void triangle(mat<4,3,float> &clipc, IShader &shader, TGAImage &image, float *zbuffer) { - mat<3,4,float> pts = (Viewport*clipc).transpose(); // transposed to ease access to each of the points +void triangle(mat<4,3,float> &clipc, IShader &shader, TGAImage &image, float *zbuffer, const Matrix& viewPortMatrix) { + mat<3,4,float> pts = (viewPortMatrix*clipc).transpose(); // transposed to ease access to each of the points mat<3,2,float> pts2; for (int i=0; i<3; i++) pts2[i] = proj<2>(pts[i]/pts[i][3]); @@ -62,8 +69,8 @@ void triangle(mat<4,3,float> &clipc, IShader &shader, TGAImage &image, float *zb Vec2f clamp(image.get_width()-1, image.get_height()-1); for (int i=0; i<3; i++) { for (int j=0; j<2; j++) { - bboxmin[j] = std::max(0.f, std::min(bboxmin[j], pts2[i][j])); - bboxmax[j] = std::min(clamp[j], std::max(bboxmax[j], pts2[i][j])); + bboxmin[j] = b3Max(0.f, b3Min(bboxmin[j], pts2[i][j])); + bboxmax[j] = b3Min(clamp[j], b3Max(bboxmax[j], pts2[i][j])); } } Vec2i P; diff --git a/examples/TinyRenderer/our_gl.h b/examples/TinyRenderer/our_gl.h index bc8ed7312..d80156904 100644 --- a/examples/TinyRenderer/our_gl.h +++ b/examples/TinyRenderer/our_gl.h @@ -3,12 +3,12 @@ #include "tgaimage.h" #include "geometry.h" -extern Matrix ModelView; -extern Matrix Projection; -void viewport(int x, int y, int w, int h); -void projection(float coeff=0.f); // coeff = -1/c -void lookat(Vec3f eye, Vec3f center, Vec3f up); + + +Matrix viewport(int x, int y, int w, int h); +Matrix projection(float coeff=0.f); // coeff = -1/c +Matrix lookat(Vec3f eye, Vec3f center, Vec3f up); struct IShader { virtual ~IShader(); @@ -17,6 +17,6 @@ struct IShader { }; //void triangle(Vec4f *pts, IShader &shader, TGAImage &image, float *zbuffer); -void triangle(mat<4,3,float> &pts, IShader &shader, TGAImage &image, float *zbuffer); +void triangle(mat<4,3,float> &pts, IShader &shader, TGAImage &image, float *zbuffer, const Matrix& viewPortMatrix); #endif //__OUR_GL_H__