Permalink
Browse files

These changes are so old I can't remember what I changed.. Whoops :P

  • Loading branch information...
1 parent 1322988 commit 4425f94bc5e287d24a2e68eb02dc410bb61d03bf @jhaberstro committed Sep 29, 2012
View
5 README
@@ -0,0 +1,5 @@
+Author: Jedd Haberstro (jhaberstro at gmail.com)
+
+Description: I wrote this project to better understand the 3D rendering pipeline and to try out some C++11 features. It's "shader based" which means you can write your graphics shaders in C++ and just pass the shader as a function pointer to the renderer. It supports texturing/abitrary attribute interpolation, triangle lists and triangle strips, clockwise or counter-clockwise polygon windings, and both indexed vertex data and normal vertex arrays.
+
+This has only been tested on Mac OS X 10.7 and 10.8 with the clang compiler.
View
@@ -9,7 +9,7 @@ RESOURCE_DIR=resources
BIN_DIR=bin
OBJ_DIR=build
SOURCE_DIR=src
-SOURCES=src/main.cpp src/Framebuffer.cpp src/Renderer.cpp src/DefaultRasteriser.cpp external/stb_image/stb_image.c
+SOURCES=src/main.cpp src/Framebuffer.cpp src/Renderer.cpp src/DefaultRasteriser.cpp src/PLYLoader.cpp external/stb_image/stb_image.c
OBJECTS= $(addprefix $(OBJ_DIR)/, \
$(patsubst %.cpp, %.o, \
$(patsubst %.c, %.o, $(SOURCES))))
View
@@ -22,7 +22,7 @@ inline void process_vert(Renderer& renderer, glm::vec4& processedVert, VaryingDa
processedVert.z = ((0.5f * (far - near)) * processedVert.z) + (0.5f * (far + near));
};
-void Renderer::draw(const std::vector< VertexArray > const& attributes, size_t start, size_t num) {
+void Renderer::draw(size_t start, size_t num) {
assert(_currentVsh != nullptr);
assert(_currentFsh != nullptr);
@@ -51,9 +51,52 @@ void Renderer::draw(const std::vector< VertexArray > const& attributes, size_t s
for (size_t i = start + startOffset; i < (start + num); i += increment) {
TriangleData triangle = std::make_tuple(
glm::vec4(), glm::vec4(), glm::vec4(),
- _currentVsh->vfunc(i + indices1[0], attributes, _currentVsh->uniforms),
- _currentVsh->vfunc(i + indices1[1], attributes, _currentVsh->uniforms),
- _currentVsh->vfunc(i + indices1[2], attributes, _currentVsh->uniforms)
+ _currentVsh->vfunc(i + indices1[0], _attributes, _currentVsh->uniforms),
+ _currentVsh->vfunc(i + indices1[1], _attributes, _currentVsh->uniforms),
+ _currentVsh->vfunc(i + indices1[2], _attributes, _currentVsh->uniforms)
+ );
+
+ process_vert(*this, get_triangle_vert0(triangle), get_triangle_varying0(triangle));
+ process_vert(*this, get_triangle_vert1(triangle), get_triangle_varying1(triangle));
+ process_vert(*this, get_triangle_vert2(triangle), get_triangle_varying2(triangle));
+ default_rasteriser(this, *_currentFsh, triangle);
+
+ std::swap(indices1, indices2);
+ }
+}
+
+void Renderer::draw_indexed(size_t start, size_t num, int32_t *indices) {
+ assert(_currentVsh != nullptr);
+ assert(_currentFsh != nullptr);
+
+ size_t increment;
+ size_t startOffset;
+ size_t indices1[] = {-2, -1, 0};
+ size_t indices2[] = {-2, -1, 0};
+ if (_primitiveTopology == PrimitiveTopology::TriangleList) {
+ increment = 3;
+ startOffset = 2;
+ }
+ else if (_primitiveTopology == PrimitiveTopology::TriangleStrip) {
+ increment = 1;
+ startOffset = 2;
+ indices2[0] = -1, indices2[1] = -2, indices2[2] = 0;
+ }
+ else {
+ assert(false);
+ }
+
+ if (_winding == PolygonWinding::Clockwise) {
+ std::swap(indices1[1], indices1[2]);
+ std::swap(indices2[1], indices2[2]);
+ }
+
+ for (size_t i = start + startOffset; i < (start + num); i += increment) {
+ TriangleData triangle = std::make_tuple(
+ glm::vec4(), glm::vec4(), glm::vec4(),
+ _currentVsh->vfunc(indices[i + indices1[0]], _attributes, _currentVsh->uniforms),
+ _currentVsh->vfunc(indices[i + indices1[1]], _attributes, _currentVsh->uniforms),
+ _currentVsh->vfunc(indices[i + indices1[2]], _attributes, _currentVsh->uniforms)
);
process_vert(*this, get_triangle_vert0(triangle), get_triangle_varying0(triangle));
View
@@ -28,14 +28,19 @@ struct Viewport
class Renderer
{
friend class Pipeline;
+ enum : int { MAX_ATTRIBUTES = 10 };
public:
Renderer();
~Renderer();
- void draw(std::vector< VertexArray > const& attributes, size_t start, size_t num);
+ void draw(size_t start, size_t num);
+
+ void draw_indexed(size_t start, size_t num, int32_t* indices);
+
+ void set_attribute(int index, int components, size_t stride, void* ptr);
void set_vertex_shader(Shader& vsh);
@@ -67,8 +72,12 @@ class Renderer
PolygonWinding polygon_winding() const;
+ int max_attributes() const;
+
private:
+ VertexArray _attributes[MAX_ATTRIBUTES];
+
Viewport _viewport;
Framebuffer* _framebuffer;
Framebuffer* _depthBuffer;
@@ -94,6 +103,16 @@ inline Renderer::~Renderer() {
if (_depthBuffer) delete _depthBuffer;
}
+inline void Renderer::set_attribute(int index, int components, size_t stride, void *ptr) {
+ assert(index >= 0);
+ assert(index < MAX_ATTRIBUTES);
+ assert(ptr != nullptr);
+ _attributes[index].elementSize = sizeof(float);
+ _attributes[index].components = components;
+ _attributes[index].stride = stride;
+ _attributes[index].vertices = ptr;
+}
+
inline void Renderer::set_vertex_shader(Shader &vsh) {
_currentVsh = &vsh;
}
@@ -154,4 +173,9 @@ inline PolygonWinding Renderer::polygon_winding() const {
return _winding;
}
-#endif // JHSR_RENDERER_HPP
+inline int Renderer::max_attributes() const {
+ return MAX_ATTRIBUTES;
+}
+
+
+#endif // JHSR_RENDERER_HPP
View
@@ -50,7 +50,7 @@ struct ShaderVariable
typedef std::vector< ShaderVariable > VaryingData;
// first element of returned vector of VertShaderFunc must be the output position
-typedef VaryingData (*VertShaderFunc) (size_t vindex, std::vector< VertexArray > const& attributes, std::vector< ShaderVariable > const& uniforms);
+typedef VaryingData (*VertShaderFunc) (size_t vindex, VertexArray* attributes, std::vector< ShaderVariable > const& uniforms);
typedef glm::vec4 (*FragShaderFunc) (ShaderVariable* varyings, std::vector< ShaderVariable > const& uniforms);
// The thought is that since author of the shader is responsible
@@ -11,6 +11,11 @@ struct VertexArray
VertexArray& operator=(VertexArray const& va) { components = va.components; stride = va.stride; vertices = va.vertices; return *this; };
VertexArray(VertexArray&& va) : components(std::move(va.components)), stride(std::move(va.stride)), vertices(std::move(va.vertices)) {}
+ void* index(size_t i) {
+ return (uint8_t*)(vertices) + (elementSize * components * i) + (stride * i);
+ }
+
+ size_t elementSize;
size_t components;
size_t stride;
void* vertices;
View
@@ -16,6 +16,24 @@ struct {
void* data;
int width, height, numChannels;
} texture;
+struct {
+ std::vector< glm::vec3 > positions;
+ std::vector< glm::vec2 > texcoords;
+} cylinder;
+
+void CreateCylinder(float height, float radius, int subdiv, std::vector< glm::vec3 >& vertices, std::vector< glm::vec2 >& texcoords) {
+ float ybottom = -height * 0.5f;
+ float dangle = (2.0f * 3.14f) / float(subdiv);
+ for (float angle = 0; angle <= 2.0f * 3.14f; angle += dangle) {
+ glm::vec3 bottom(std::cosf(angle) * radius, ybottom, std::sinf(angle));
+ glm::vec3 top(bottom.x, -bottom.y, bottom.z);
+ float t = angle / (2.0f * 3.14f);
+ vertices.push_back(bottom);
+ vertices.push_back(top);
+ texcoords.push_back(glm::vec2(t, 0.0f));
+ texcoords.push_back(glm::vec2(t, 1.0f));
+ }
+}
enum : size_t
{
@@ -50,34 +68,35 @@ void calculateFPS()
}
}
-VaryingData vsh_func(size_t vindex, std::vector< VertexArray > const& attributes, std::vector< ShaderVariable > const& uniforms) {
- auto& position = reinterpret_cast< glm::vec3* >(attributes[0].vertices)[vindex];
- auto& color = reinterpret_cast< glm::vec4* >(attributes[1].vertices)[vindex];
- auto& uv = reinterpret_cast< glm::vec2* >(attributes[2].vertices)[vindex];
+VaryingData vsh_func(size_t vindex, VertexArray* attributes, std::vector< ShaderVariable > const& uniforms) {
+ auto& position = *reinterpret_cast< glm::vec3* >(attributes[0].index(vindex));
+ auto& uv = *reinterpret_cast< glm::vec2* >(attributes[1].index(vindex));
glm::mat4x4 const& modelview = uniforms[0].m4;
glm::mat4x4 const& projection = uniforms[1].m4;
VaryingData output;
output.push_back(projection * modelview * glm::vec4(position.x, position.y, position.z, 1.0f));
- output.push_back(color);
output.push_back(uv);
return output;
}
glm::vec4 fsh_func(ShaderVariable* varyings, std::vector< ShaderVariable > const& uniforms) {
- glm::ivec2 st(varyings[1].v2.x * texture.width, varyings[1].v2.y * texture.height);
- uint32_t* pixels = reinterpret_cast< uint32_t* >(texture.data);
- uint32_t pcolor = pixels[(st.y * texture.width) + st.x];
- // return glm::vec4(varyings[1].v2.x, varyings[1].v2.y, 0.0f, 1.0f);
- return glm::vec4(float(pcolor & 0xff) / 255.0f, float((pcolor >> 8) & 0xff) / 255.0f, float((pcolor >> 16) & 0xff) / 255.0f, float((pcolor >> 24) & 0xff) / 255.0f);
- // return (varyings[0].v4);
+ struct rgb8 { uint8_t r, g, b; };
+ glm::ivec2 st(varyings[0].v2.x * texture.width, varyings[0].v2.y * texture.height);
+ rgb8* pixels = reinterpret_cast< rgb8* >(texture.data);
+ size_t index = std::min((st.y * texture.width) + st.x, (texture.width * texture.height) - 1);
+ rgb8 pcolor = pixels[index];
+ return glm::vec4(pcolor.r / 255.0f, pcolor.g / 255.0f, pcolor.b / 255.0f, 255.0f);
}
void init(void) {
texture.data = nullptr;
- texture.data = stbi_load("/Users/jhaberstro/Personal-Projects/software-rasterizer/project/bin/NeHe.png", &texture.width, &texture.height, &texture.numChannels, 4);
+ texture.data = stbi_load("Nehe.png", &texture.width, &texture.height, &texture.numChannels, 3);
+ std::printf("Num channels: %i\n", texture.numChannels);
assert(texture.data != nullptr);
+ CreateCylinder(1.0f, 1.0f, 100, cylinder.positions, cylinder.texcoords);
+
renderer.set_framebuffer(WIDTH, HEIGHT, 4);
renderer.set_viewport(0, 0, WIDTH, HEIGHT);
renderer.set_depth_range(0.0f, 1.0f);
@@ -96,46 +115,11 @@ void init(void) {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
-void GLEquivalient() {
- auto modelview = glm::translate(glm::mat4x4(), glm::vec3(0.0f, 0.0f, -3.5f)) * glm::rotate(glm::mat4x4(), float(0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
- auto projection = glm::perspective(60.0f, static_cast< float >(WIDTH) / static_cast< float >(HEIGHT), 0.1f, 100.0f);
- glm::vec3 positions[] = {glm::vec3(-1.0f, -1.0f, 0.0f), glm::vec3(1.0f, -1.0f, 0.0f), glm::vec3(-1.0f, 1.0f, 0.0f), glm::vec3(1.0f, 1.0f, 0.0f) };
- glm::vec4 colors[] = { glm::vec4(1.0f, 0.0f, 0.0f, 1.0f), glm::vec4(0.0f, 1.0f, 0.0f, 1.0f), glm::vec4(0.0f, 0.0f, 1.0f, 1.0f), glm::vec4(1.0f) };
- glViewport(0, 0, WIDTH, HEIGHT);
- glMatrixMode(GL_PROJECTION);
- glLoadMatrixf(&projection[0][0]);
- glMatrixMode(GL_MODELVIEW);
- glLoadMatrixf(&modelview[0][0]);
- glEnable(GL_DEPTH_TEST);
-
- glClearColor(0, 0, 0, 0);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- glBegin(GL_TRIANGLE_STRIP);
- for (int i = 0; i < sizeof(positions) / sizeof(positions[0]); ++i) {
- glColor4fv((GLfloat*)(colors + i));
- glVertex3fv((GLfloat*)(positions + i));
- }
- glEnd();
-}
-
-void draw() {
- uint32_t clearColor = 0x00000000;
- float depthClear = INFINITY;
- renderer.depth_buffer().clear(&depthClear);
- Framebuffer& framebuffer = renderer.framebuffer();
- framebuffer.clear(&clearColor);
-
+void draw_quad() {
glm::vec3 positions[] = {glm::vec3(-1.0f, -1.0f, 0.0f), glm::vec3(1.0f, -1.0f, 0.0f), glm::vec3(-1.0f, 1.0f, 0.0f), glm::vec3(1.0f, 1.0f, 0.0f) };
- glm::vec4 colors[] = { glm::vec4(1.0f, 0.0f, 0.0f, 1.0f), glm::vec4(0.0f, 1.0f, 0.0f, 1.0f), glm::vec4(0.0f, 0.0f, 1.0f, 1.0f), glm::vec4(1.0f) };
glm::vec2 uvs[] = { glm::vec2(0.0f, 0.0f), glm::vec2(1.0f, 0.0f), glm::vec2(0.0f, 1.0f), glm::vec2(1.0f, 1.0f) };
- VertexArray pa(3, 0, positions);
- VertexArray ca(4, 0, colors);
- VertexArray ta(2, 0, uvs);
- std::vector< VertexArray > attributes;
- attributes.push_back(pa);
- attributes.push_back(ca);
- attributes.push_back(ta);
+ renderer.set_attribute(0, 3, 0, positions);
+ renderer.set_attribute(1, 2, 0, uvs);
static int angle = 0;
angle = (angle + 1) % 360;
@@ -148,8 +132,41 @@ void draw() {
renderer.set_vertex_shader(vsh);
renderer.set_fragment_shader(fsh);
+ renderer.set_polygon_winding(PolygonWinding::CounterClockwise);
renderer.set_primitive_topology(PrimitiveTopology::TriangleStrip);
- renderer.draw(attributes, 0, 4);
+ renderer.draw(0, 4);
+}
+
+void draw_cylinder() {
+ renderer.set_attribute(0, 3, 0, &cylinder.positions[0].x);
+ renderer.set_attribute(1, 2, 0, &cylinder.texcoords[0].x);
+
+ static int angle = 0;
+ angle = (angle + 1) % 360;
+ auto modelview = glm::translate(glm::mat4x4(), glm::vec3(0.0f, 0.0f, -3.5f)) * glm::rotate(glm::mat4x4(), float(angle), glm::vec3(1.0f, 0.0f, 0.0f));
+ auto projection = glm::perspective(60.0f, static_cast< float >(WIDTH) / static_cast< float >(HEIGHT), 0.1f, 100.0f);
+ Shader vsh(vsh_func), fsh(fsh_func);
+ vsh.uniforms.push_back(modelview);
+ vsh.uniforms.push_back(projection);
+
+ renderer.set_vertex_shader(vsh);
+ renderer.set_fragment_shader(fsh);
+ renderer.set_primitive_topology(PrimitiveTopology::TriangleStrip);
+ renderer.set_polygon_winding(PolygonWinding::CounterClockwise);
+ renderer.draw(0, cylinder.positions.size());
+ renderer.set_polygon_winding(PolygonWinding::Clockwise);
+ renderer.draw(0, cylinder.positions.size());
+}
+
+void draw() {
+ uint32_t clearColor = 0x00000000;
+ float depthClear = INFINITY;
+ renderer.depth_buffer().clear(&depthClear);
+ Framebuffer& framebuffer = renderer.framebuffer();
+ framebuffer.clear(&clearColor);
+
+ //draw_quad();
+ draw_cylinder();
glBindTexture(GL_TEXTURE_2D, framebuffer_tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, framebuffer.width(), framebuffer.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer.pixels());
@@ -197,4 +214,4 @@ int main(int argc, char** argv) {
glutMainLoop();
return 0;
-}
+}
@@ -22,6 +22,7 @@
// "-I/usr/lib/gcc/i686-apple-darwin11/4.2.1/include/",
"-isystem external/libcxx/include/",
"-I/Users/jhaberstro/Personal-Projects/software-rasterizer/project/external/glm/",
+ "-I/Users/jhaberstro/Personal-Projects/software-rasterizer/project/external/stb_image/",
//"-I/usr/lib/include/c++/v1/",
"-I/usr/lib/clang/3.1/include/",
"-isysroot", "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk"
Oops, something went wrong.

0 comments on commit 4425f94

Please sign in to comment.