Stephen A
6 posts
None
I'm following this 3d course how OpenGL works and had a problem with gouraud shading. My render is not coming out correctly. I've been fussing with it and thought i'd ask for help. I'll continue studying but in the meantime any help is appreciated.
The major problem i'm having with my render is that when i try to incorporate the normals associated
with each vertex with the light source i get a wrong output. It's meant to be smoothly shaded but
it's not even close. I'm using the obj model that comes with the course that has the normals given per vertex

Screenshots:
The first one is when i don't check if the interpolated intensity is > 0
The other is when i do

Here's the code(somewhat abbreviated):
  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 v3f lightDir(1.0f, -1.0f, 1.0f); void drawModel() { int[] zBuffer = new int[width*height]; // zBuffer filled with lowest possible int value for(int i = 0; i < model->nfaces(); i++) { std::vector faces = model->faces(i); v3i screen_coords[3]; v3f world_coords[3]; float intensity[3]; for(int j = 0; j < 3; j++) { v3f triangleVertex = model->vertex(faces[i]); int x = (int)(triangleVertex.x+1.0f * width / 2); int y = (int)(triangleVertex.y+1.0f * height / 2); screen_coords[j] = v3i(x, y, (int)triangleVertex.z); world_coords[j] = triangleVertex; //This gets the normal associated with this vertex v3f vertexNormal = model->norm(i, j).normalize(); // dot product of the light and the normal( for diffuse lighting) intensity[j] = vertexNormal*lightDir; } drawTriangle(screen_coords, intensity, zBuffer); } } 

The drawTriangle function computes the barycentric coordinates for each point
in the bounding box of the triangle to be drawn and checks if they are positive and
if their sum is less than 1

My code for rendering triangles
The scalars associated with each vertex are u, v, and q
  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 void drawTriangle(v3i* screen_coords, float* intensity, int* zBuffer) { // sort the vertices of the triangles using x and intensity relative to the sort // assume we have the min, max x and min, max y values that enclose the bounding box v3i v0 = screen_coords[2] - screen_coords[0]; v3i v1 = screen_coords[1] - screen_coords[0]; float dot00 = v0*v0; float dot01 = v0*v1; float dot11 = v1*v1; float u, v; float denom = 1.0f / (dot00 *dot11 - dot01 *dot01); for(int y = ymin; y < ymax; y++) { for(int x= xmin; x < xmax; x++) { v3i p(x, y, 0); v3i v2 = p - screen_coords[0]; float dot02 = v0*v2; float dot12 = v1*v2; u = (dot02*dot11 - dot12*dot01) * denom; v = (dot00*dot12 - dot01*dot02) * denom; if((u >= 0) && (v >= 0) && (u+v < 1)) { q = 1-u-v; float bc[] = {u, v, q}; //interpolate z for(int i =0; i < 3; i++) { p.z += (screen_coords[i].z * bc[i]); } if(zBuffer[x+y*width] < p.z) { // where i actually use the intensity for gouraud shading float intensity = intensity[0]*u + intensity[1]*v + intensity[2]*q; // multiplies the intensity by 255.0f for r, g, b components and // or's the values together to get the color int color = createColor(intensity); setPixel(x, y, color); } } } } } 

Thanks
Stephen A
6 posts
None
Edited by Stephen A on Reason: image issue
I figured it out. My first problem was casting the z of the world coordinates to an int. My second problem was multiplying the intensities by the wrong affine scalars. Here's my new result

[attachment=65]ScreenShot2016-03-07at3.53.43PM-min.png[/attachment]

Not sure why the image is cut
504 posts
clear the depth buffer as well
Stephen A
6 posts
None
Thanks, it's working on my machine. It's when i posted the screenshot that the image got cut, not sure why
Carsten Holtkamp
26 posts
Do you know about http://embree.github.io/renderer.html ?
Carsten Holtkamp
26 posts
The course, which you are referring to, is very interesting. I think parts of Michael Abrash’s Graphics Programming Black Book, are a good addition to the course, as well.

In 2001 he released his book to the public.

http://www.drdobbs.com/parallel/g...-programming-black-book/184404919

Here is a single-page online version, of the chapter covering gouraud-shading.

Source code in C and Assembly is available,
eg @
http://devel.archefire.org/docs/p.../MichaelAbrashBlackBookSource.zip
Stephen A
6 posts
None
I didn't know about that renderer but i'm glad i can learn from the source. I'm new to all this. Thanks for the references though, especially abrash's, adding them to my study list. Do you know how relevant the asm code that comes with the black book is in terms of today's machines and have you done any work on 3d renderers?
Carsten Holtkamp
26 posts
Edited by Carsten Holtkamp on Reason: added executeable file formats
It depends (like usually):
On your interest and the field you want to specialize.

Knowledge is always better, but you need to focus on some things, life is short.

If Intel hires you to focus on the CPU-Renderer, then the assembly code might be very interesting.
If you focus on cross platform software development, assembly language might never cross your ways.
In many cases inline assembly is enough, but in many cases even that is not useful (there is no magic in inline). en.wikipedia.org/wiki/Inline_assembler

Assembly language is a misleading term:
To assemble, to collect, to gather.
Assembler is the piece of software that converts the text to machine readable code;
instruction and data sequences, which ordered in different sections, so that the Operating system (OS) can provide it to the CPU.
The final file layout depends on the executeable file format that the OS is supporting.

Actually, an assembler is part of the tool-chain if you write C-Code, it is called behind the scene at some late Stage during the compile-progress.
GCC calls GAS; try
 1 as –version 

in a Ginux (I use that term for a Linux based OS, cause Linux is just the name of the Kernel) shell. If you installed gcc, the assembler tells it version.

I know, most of you people here use Microsoft's OS’s.

Most Assembly language syntaxes aren’t standardized (if there is any?) unlike C/C++.
So the language depends fully on the underlying Assembler (gas/nasm/yasm to name some).
Two syntaxes are more popular, AT&T (used by gas) and Intel (masm, nasm).
The major sum of keywords in Assembly language derived from the processor manufacturer’s CPU manual. These are called mnemonics.
mnemonic from greek μνήμη → memory, to remember, keep in mind.
Some are short words, some are acronyms, like:

push, pop, add, cmp, call, lea, je, xor

So the “language” depends on the Assembler + underlying CPU.
I also said that the final file is organized for the operating system, in a binary (executable file format the operating system understands). It has to follow the OS’s calling conventions and use the OS’s syscalls. So finally it depends on the Assembler, the CPU and the OS.
And there are many CPU’s.

You can assemble the code of the book, but it is 32-bit code.
Like, you compile 32 bit code with:
 1 gcc -m32 -o output32 hello.c 

You can do the same for asm files with:
 1 as --32 -o movtest3.o movtest3.s 

but you need to link it also:
 1 ld -melf_i386 -dynamic-linker /lib/ld-linux.so.2 -L/usr/lib/ -lc -o movtest3 movtest3.o 

There are many documents outside, were the movement from 32 to 64 bit assembly language is described. IMO it is harder to read the Intel manual than to code :)
There are manuals for the manual aswell ^^

ASM (x86/x86_64)
https://software.intel.com/en-us/...cles/introduction-to-x64-assembly
http://eli.thegreenplace.net/tag/assembly

C and asm
https://www.recurse.com/blog/7-understanding-c-by-learning-assembly

Calling Conventions:
http://www.agner.org/optimize/calling_conventions.pdf

Executable file formats:
en.wikipedia.org/wiki/Portable_Executable

There are several other resources in this forum already.

To answer your second question, I think I can definitely say that I am not a renderer-programming expert.

I am 43, started coding at age of 11, but had many times where I did something else. Since 2007 I did 2 years on 3D Design and in the past 7 years I focused on linux development, C-Programming, 64-Bit Linux Assembly, Bash-Programming and other things.

I dove deep in the source code of blender.org and enlightment.org, since 2 Years I do OpenGL and SDL2 Coding, some cross-platform (android) work. And I built an interactive developer help, which is svg based.
Carsten Holtkamp
26 posts
One addition to my assembler remarks:
Most Mnemonics are representations of the equivalent Processors Operations Codes (OpCodes).
They are unique bit sequences, identified during the CPU’s instruction cycle (sometimes called fetch-decode-execute cycle) and presented as hexadecimal values.

https://en.wikipedia.org/wiki/Instruction_cycle

It seems that you are serious about writing renderer/graphics code.
You should check Philip Rideout’s page. He is a professional and experienced Graphics Developer.

http://prideout.net/

He wrote:
Kazmath is a simple 3D maths library

And there are very interesting pieces of code on:
http://github.prideout.net/

and his old blog aswell:
http://prideout.net/blog/

Happy coding from Germany
Stephen A
6 posts
None