OpenGL Lecture on Computer Graphics Basics

undefined
 
C
o
m
p
u
t
e
r
 
G
r
a
p
h
i
c
s
 
CSE 167 [Win 17], Lecture 8: OpenGL 2
Ravi Ramamoorthi
 
 
 
 
 
http://viscomp.ucsd.edu/classes/cse167/wi17
 
T
o
 
D
o
 
Continue working on HW 2.  Can be difficult
Class lectures, programs primary source
Can leverage many sources (GL(SL) book, excellent
online documentation, see links class website)
It is a good idea to copy (and modify) relevant segments
 
M
e
t
h
o
d
o
l
o
g
y
 
f
o
r
 
L
e
c
t
u
r
e
 
Make mytest1 more
ambitious
Sequence of steps
Demo
 
R
e
v
i
e
w
 
o
f
 
L
a
s
t
 
D
e
m
o
 
Changed floor to all white, added global for teapot and
teapotloc, moved geometry to new header file
Demo 0 [set DEMO to 4 all features]
 
#include <GL/glut.h> //also <GL/glew.h>; <GLUT/glut.h> for Mac OS
#include 
shaders.h
#include 
geometry.h
 
int mouseoldx, mouseoldy ; // For mouse motion
GLfloat eyeloc = 2.0 ; // Where to look from; initially 0 -2, 2
GLfloat teapotloc = -0.5 ; // ** NEW ** where the teapot is located
GLint animate = 0 ; // ** NEW ** whether to animate or not
GLuint vertexshader, fragmentshader, shaderprogram ; // shaders
 
const int DEMO = 0 ; // ** NEW ** To turn on and off features
 
O
u
t
l
i
n
e
 
Review of demo from last lecture
Basic geometry setup for cubes (pillars), colors
Single geometric object, but multiple colors for pillars
Matrix Stacks and Transforms (draw 4 pillars)
Depth testing (Z-buffering)
Animation (moving teapot)
Texture Mapping (wooden floor)
 
Best source for OpenGL is the red book and GLSL book.  Of course,
this is more a reference manual than a textbook, and you are better off
implementing rather reading end to end.
 
G
e
o
m
e
t
r
y
 
B
a
s
i
c
 
S
e
t
u
p
 
1
 
 
const int numobjects = 2 ; // number of objects for buffer
const int numperobj  = 3 ;
const int ncolors = 4 ;
GLUint VAOs[numobjects+ncolors], teapotVAO; // VAO (Vertex Array
Object) for each primitive object
GLuint buffers[numperobj*numobjects+ncolors]
, teapotbuffers[3]
 ; 
  
//
** NEW ** List of buffers for geometric data
GLuint objects[numobjects] ; // 
** NEW ** 
For each object
GLenum PrimType[numobjects] ;
GLsizei NumElems[numobjects] ;
 
// For the geometry of the teapot
std::vector <glm::vec3> teapotVertices;
std::vector <glm::vec3> teapotNormals;
std::vector <unsigned int> teapotIndices;
 
// To be used as a matrix stack for the modelview.
std::vector <glm::mat4> modelviewStack;
 
 
 
G
e
o
m
e
t
r
y
 
B
a
s
i
c
 
S
e
t
u
p
 
2
 
 
// ** NEW ** Floor Geometry is specified with a vertex array
// ** NEW ** Same for other Geometry
 
enum {Vertices, Colors, Elements} ; // For arrays for object
enum {FLOOR, CUBE} ; // For objects, for the floor
 
const GLfloat floorverts[4][3] = {
  {0.5, 0.5, 0.0}, {-0.5, 0.5, 0.0}, {-0.5, -0.5, 0.0}, {0.5, -0.5,
0.0}
} ;
const GLfloat floorcol[4][3] = {
  {1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}
} ;
const GLubyte floorinds[1][6] = { {0, 1, 2, 0, 2, 3} } ;
const GLfloat floortex[4][2] = {
  {1.0, 1.0}, {0.0, 1.0}, {0.0, 0.0}, {1.0, 0.0}
} ;
 
 
 
C
u
b
e
 
g
e
o
m
e
t
r
y
 
(
f
o
r
 
p
i
l
l
a
r
s
)
 
 
const GLfloat wd = 0.1 ;
const GLfloat ht = 0.5 ;
const GLfloat _cubecol[4][3] = {
  {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, {1.0, 1.0,
0.0} } ;
const GLfloat cubeverts[8][3] = {
  {-wd, -wd, 0.0}, {-wd, wd, 0.0}, {wd, wd, 0.0}, {wd, -wd, 0.0},
  {-wd, -wd, ht}, {wd, -wd, ht}, {wd, wd, ht}, {-wd, wd, ht}
} ;
GLfloat cubecol[
12
][3] ;
const GLubyte cubeinds[
12
][
3
] = {
  {0, 1, 2
}
, 
{0, 2, 
3}, // BOTTOM
  {4, 5, 6
}
, 
{4, 6, 
7}, // TOP
  {0, 4, 7
}
, 
{0, 7, 
1}, // LEFT
  {0, 3, 5
}
, 
{0, 5, 
4}, // FRONT
  {3, 2, 6
}
, 
{3, 6, 
5}, // RIGHT
  {1, 7, 6
}
, 
{1, 6, 
2}  // BACK
} ;
 
I
n
i
t
i
a
l
i
z
e
 
G
e
o
m
e
t
r
y
 
F
u
n
c
t
i
o
n
 
// This function takes in a vertex, color, index and type array
void initobject(GLuint object, GLfloat * vert, GLint sizevert, GLfloat * col, GLint
sizecol, GLubyte * inds, GLint sizeind, GLenum type) {
   int offset = object * numperobj ;
   glBindVertexArray(VAOs[object]);
   glBindBuffer(GL_ARRAY_BUFFER, buffers[Vertices + offset]);
   glBufferData(GL_ARRAY_BUFFER, sizevert, vert, GL_STATIC_DRAW);
   // Use layout location 0 for the vertices
   glEnableVertexAttribArray(0);
   glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0);
   glBindBuffer(GL_ARRAY_BUFFER, buffers[Colors + offset]);
   glBufferData(GL_ARRAY_BUFFER, sizecol, col, GL_STATIC_DRAW);
   // Use layout location 1 for the colors
   glEnableVertexAttribArray(1);
   glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0);
   glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[Elements + offset]);
   glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeind, inds, GL_STATIC_DRAW);
   PrimType[object] = type;
   NumElems[object] = sizeind;
   // Prevent further modification of this VAO by unbinding it
   glBindVertexArray(0);}
 
I
n
i
t
i
a
l
i
z
e
 
C
u
b
e
s
 
w
i
t
h
 
 
C
o
l
o
r
s
 
1
 
void initcubes(GLuint object, GLfloat * vert, GLint sizevert, GLubyte *
inds, GLint sizeind, GLenum type) {
 
for (int i = 0; i < ncolors; i++) {
  
for (int j = 0; j < 8; j++)
   
for (int k = 0; k < 3; k++)
    
cubecol[j][k] = _cubecol[i][k];
  
glBindVertexArray(VAOs[object + i]);
  
int offset = object * numperobj;
  
int base = numobjects * numperobj;
  
glBindBuffer(GL_ARRAY_BUFFER, buffers[Vertices + offset]);
  
glBufferData(GL_ARRAY_BUFFER, sizevert, vert, GL_STATIC_DRAW);
  
// Use layout location 0 for the vertices
  
glEnableVertexAttribArray(0);
  
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 *
sizeof(GLfloat), 0);
  
glBindBuffer(GL_ARRAY_BUFFER, buffers[base + i]);
  
glBufferData(GL_ARRAY_BUFFER, sizeof(cubecol), cubecol,
GL_STATIC_DRAW);
 
I
n
i
t
i
a
l
i
z
e
 
C
u
b
e
s
 
w
i
t
h
 
 
C
o
l
o
r
s
 
2
 
...
  
// Use layout location 1 for the colors
  
glEnableVertexAttribArray(1);
  
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 *
sizeof(GLfloat), 0);
  
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[Elements +
offset]);
  
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeind, inds,
GL_STATIC_DRAW);
  
PrimType[object] = type;
  
NumElems[object] = sizeind;
  
// Prevent further modification of this VAO by unbinding it
  
glBindVertexArray(0);
 
}
}
//in init
 initobject(FLOOR, (GLfloat *) floorverts, sizeof(floorverts), (GLfloat
*) floorcol, sizeof (floorcol), (GLubyte *) floorinds, sizeof
(floorinds), GL_TRIANGLES) ;
  initcubes(CUBE, (GLfloat *)cubeverts, sizeof(cubeverts), (GLubyte
*)cubeinds, sizeof(cubeinds), GL_TRIANGLES);
  loadteapot();
 
D
r
a
w
i
n
g
 
w
i
t
h
/
w
i
t
h
o
u
t
 
C
o
l
o
r
s
 
 
// And a function to draw with them, similar to drawobject but with color
void drawcolor(GLuint object, GLuint color) {
   glBindVertexArray(VAOs[object + color]);
   glDrawElements(PrimType[object], NumElems[object], GL_UNSIGNED_BYTE,
0);
   glBindVertexArray(0);
}
 
void drawobject(GLuint object) {
   glBindVertexArray(VAOs[object]);
   glDrawElements(PrimType[object], NumElems[object], GL_UNSIGNED_BYTE,
0);
   glBindVertexArray(0);
}
 
void loadteapot() // See source code for details if interested
 
O
u
t
l
i
n
e
 
Review of demo from last lecture
Basic geometry setup for cubes (pillars), colors
Single geometric object, but multiple colors for pillars
Matrix Stacks and Transforms (draw 4 pillars)
Depth testing (Z-buffering)
Animation (moving teapot)
Texture Mapping (wooden floor)
 
Best source for OpenGL is the red book and GLSL book.  Of course,
this is more a reference manual than a textbook, and you are better off
implementing rather reading end to end.
 
S
u
m
m
a
r
y
 
O
p
e
n
G
L
 
V
e
r
t
e
x
 
T
r
a
n
s
f
o
r
m
s
Object coords
(x y z w)
t
 vertex
Modelview matrix
[Object Transforms
and glm::lookAt]
Projection matrix
[3D to 2D, usually
glm::perspective]
 
Eye coordinates
(used for lighting)
Perspective Divide
(Dehomogenization)
 
Clip coordinates
Viewport Transform
(glViewport)
 
Normalized Device
Coordinates
 
Window Coords
 
T
r
a
n
s
f
o
r
m
a
t
i
o
n
s
 
Matrix Stacks
Old OpenGL: glPushMatrix, glPopMatrix, glLoad, glMultMatrixf
Useful for hierarchically defined figures, placing pillars
Current recommendation is STL stacks managed yourself, which is
done in mytest2. 
(You must manage the stack yourself for HW 2).
Transforms
Write your own translate, scale, rotate for HW 1 and HW 2
C
a
r
e
f
u
l
 
o
f
 
O
p
e
n
G
L
 
c
o
n
v
e
n
t
i
o
n
:
 
I
n
 
o
l
d
-
s
t
y
l
e
,
 
R
i
g
h
t
-
m
u
l
t
i
p
l
y
 
c
u
r
r
e
n
t
m
a
t
r
i
x
 
(
l
a
s
t
 
i
s
 
f
i
r
s
t
 
a
p
p
l
i
e
d
)
.
 
 
g
l
m
 
o
p
e
r
a
t
o
r
s
 
f
o
l
l
o
w
 
t
h
i
s
 
s
o
m
e
t
i
m
e
s
.
Also gluLookAt (glm::lookAt), gluPerspective (glm::perspective)
Remember just matrix like any other transform, affecting modelview
See mytest for how to best implement these ideas
 
D
r
a
w
i
n
g
 
P
i
l
l
a
r
s
 
1
 
(
i
n
 
d
i
s
p
l
a
y
)
 
   // 1st pillar
: Right-multiply modelview as in old OpenGL
   
p
ushMatrix(
modelview
) ;
  // push/pop functions for stack
       
modelview = modelview * glm::translate(identity, glm::vec3(-0.4, -
0.4, 0.0)) ;  // build translation matrix
  
glUniformMatrix4fv(modelviewPos, 1, GL_FALSE,
&(modelview)[0][0]);
       drawcolor(CUBE, 0) ;
   
p
opMatrix(
modelview
) ;
 
   // 2nd pillar
   
p
ushMatrix(
modelview
) ;
       
modelview = modelview * glm::translate(identity, glm::vec3(0.4, -
0.4, 0.0)) ;  // build translation matrix
  
glUniformMatrix4fv(modelviewPos, 1, GL_FALSE,
&(modelview)[0][0]);
       drawcolor(CUBE, 1) ;
   
p
opMatrix(
modelview
) ;
// Function pushes specified matrix onto the modelview stack
void pushMatrix(glm::mat4 mat) {
 
modelviewStack.push_back(glm::mat4(mat)); }
 
 
D
r
a
w
i
n
g
 
P
i
l
l
a
r
s
 
2
 
 // 3rd pillar
 
pushMatrix(modelview);
 
modelview = modelview * glm::translate(identity,
glm::vec3(0.4, 0.4, 0.0));
 
glUniformMatrix4fv(modelviewPos, 1, GL_FALSE,
&(modelview)[0][0]);
 
drawcolor(CUBE, 2) ;
 
popMatrix(modelview);
 // 4th pillar
 
pushMatrix(modelview);
 
modelview = modelview * glm::translate(identity, glm::vec3(-
0.4, 0.4, 0.0));
 
glUniformMatrix4fv(modelviewPos, 1, GL_FALSE,
&(modelview)[0][0]);
 
drawcolor(CUBE, 3) ;
 
popMatrix(modelview);
// This function pops a matrix from the modelview stack void
popMatrix(glm::mat4& mat) {
 
if (modelviewStack.size()) {
  
mat = glm::mat4(modelviewStack.back());
  
modelviewStack.pop_back();
 
}
 
else { // Just to prevent errors when popping from an empty
stack.
  
mat = glm::mat4(1.0f);
 
}
}
 
 
D
e
m
o
 
Demo 1
Does order of drawing matter?
What if I move floor after pillars in code?
Is this desirable?  If not, what can I do about it?
 
O
u
t
l
i
n
e
 
Review of demo from last lecture
Basic geometry setup for cubes (pillars), colors
Single geometric object, but multiple colors for pillars
Matrix Stacks and Transforms (draw 4 pillars)
Depth testing (Z-buffering)
Animation (moving teapot)
Texture Mapping (wooden floor)
 
Best source for OpenGL is the red book and GLSL book.  Of course,
this is more a reference manual than a textbook, and you are better off
implementing rather reading end to end.
 
D
o
u
b
l
e
 
B
u
f
f
e
r
i
n
g
 
New primitives draw over (replace) old objects
Can lead to jerky sensation
Solution: double buffer.  Render into back
(offscreen) buffer.  When finished, swap buffers
to display entire image at once.
Changes in main and display
   
glutInitDisplayMode (
GLUT_DOUBLE
 | GLUT_RGB | GLUT_DEPTH);
 
   
glutSwapBuffers() ;
   glFlush ();
 
 
 
T
u
r
n
i
n
g
 
o
n
 
D
e
p
t
h
 
t
e
s
t
 
(
Z
-
b
u
f
f
e
r
)
 
OpenGL uses a Z-buffer for depth tests
For each pixel, store nearest Z value (to camera) so far
If new fragment is closer, it replaces old z, color
[
less than
 can be over-ridden in fragment program]
Simple technique to get accurate visibility
(Be sure you know what fragments and pixels are)
Changes in main fn, display to Z-buffer
 
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | 
GLUT_DEPTH
);
glClear (GL_COLOR_BUFFER_BIT |
 GL_DEPTH_BUFFER_BIT
);
In init function
  
glEnable(GL_DEPTH_TEST) ;
 glDepthFunc(GL_LESS) ; // The default option
 
 
 
D
e
m
o
 
Demo 2
Does order of drawing matter any more?
What if I change near plane to 0?
Is this desirable?  If not, what can I do about it?
 
O
u
t
l
i
n
e
 
Review of demo from last lecture
Basic geometry setup for cubes (pillars), colors
Single geometric object, but multiple colors for pillars
Matrix Stacks and Transforms (draw 4 pillars)
Depth testing (Z-buffering)
Animation (moving teapot)
Texture Mapping (wooden floor)
 
Best source for OpenGL is the red book and GLSL book.  Of course,
this is more a reference manual than a textbook, and you are better off
implementing rather reading end to end.
 
D
e
m
o
 
Demo 3
Notice how teapot cycles around
And that I can pause and restart animation
And do everything else (zoom etc.) while teapot
moves in background
 
D
r
a
w
i
n
g
 
T
e
a
p
o
t
 
(
i
n
 
d
i
s
p
l
a
y
)
 
 //  ** NEW ** Put a teapot in the middle that animates
  
 
pushMatrix(modelview);
 
modelview = modelview * glm::translate(identity,
glm::vec3(teapotloc, 0.0, 0.0));
    //  The following two transforms set up and center the teapot
    //  Transforms right-multiply the modelview matrix (top of the stack)
 
modelview = modelview * glm::translate(identity, glm::vec3(0.0,
0.0, 0.1));
 
modelview = modelview * glm::rotate(identity, glm::pi<float>() /
2.0f, glm::vec3(1.0, 0.0, 0.0));
 
float size = 0.235f; // Teapot size
 
modelview = modelview * glm::scale(identity, glm::vec3(size, size,
size));
 
glUniformMatrix4fv(modelviewPos, 1, GL_FALSE, &(modelview)[0][0]);
    
 
drawteapot() ;
 
popMatrix(modelview);
 
void drawteapot() {// drawteapot() function in geometry.h
 
glBindVertexArray(teapotVAO);
 
glDrawElements(GL_TRIANGLES, teapotIndices.size(),
GL_UNSIGNED_INT, 0);
 
glBindVertexArray(0);
}
 
 
S
i
m
p
l
e
 
A
n
i
m
a
t
i
o
n
 
r
o
u
t
i
n
e
 
// ** NEW ** in this assignment, is an animation of a teapot
// Hitting p will pause this animation; see keyboard callback
 
void animation(void) {
  teapotloc = teapotloc + 0.005 ;
  if (teapotloc > 0.5) teapotloc = -0.5 ;
  glutPostRedisplay() ;
}
 
K
e
y
b
o
a
r
d
 
c
a
l
l
b
a
c
k
 
(
p
 
t
o
 
p
a
u
s
e
)
 
GLint animate = 0 ; // ** NEW ** whether to animate or not
 
void keyboard (unsigned char key, int x, int y)
{
  switch (key) {
  case 27:  // Escape to quit
    exit(0) ;
    break ;
  case 'p': // ** NEW ** to pause/restart animation
    animate = !animate ;
      if (animate) glutIdleFunc(animation) ;
      else glutIdleFunc(NULL) ;
    break ;
  default:
    break ;
  }
}
 
O
u
t
l
i
n
e
 
Review of demo from last lecture
Display lists (extend init for pillars)
Matrix stacks and transforms (draw 4 pillars)
Depth testing or z-buffering
Animation (moving teapot)
Texture mapping (wooden floor) [mytest3]
 
N
e
w
 
g
l
o
b
a
l
s
 
a
n
d
 
b
a
s
i
c
 
s
e
t
u
p
 
// In mytest3.cpp
GLubyte woodtexture[256][256][3] ; // texture (from grsites.com)
GLuint texNames[1] ; // texture buffer
GLuint istex ;  // blend parameter for texturing
GLuint islight ; // for lighting
GLint texturing = 1 ; // to turn on/off texturing
GLint lighting = 1 ; //
 
to turn on/off lighting
 
// In Display
 
glUniform1i(islight,0) ; // Turn off lighting (except on teapot, later)
 glUniform1i(istex,texturing) ;
 drawtexture(FLOOR,texNames[0]) ; // Texturing floor
 // drawobject(FLOOR) ;
g
l
U
n
i
f
o
r
m
1
i
(
i
s
t
e
x
,
0
)
 
;
 
/
/
 
O
t
h
e
r
 
i
t
e
m
s
 
a
r
e
n
'
t
 
t
e
x
t
u
r
e
d
 
S
i
m
p
l
e
 
T
o
g
g
l
e
s
 
f
o
r
 
K
e
y
b
o
a
r
d
 
 case 't': // ** NEW ** to turn on/off texturing ;
    texturing = !texturing ;
    glutPostRedisplay() ;
    break ;
  case 's': // ** NEW ** to turn on/off shading (always smooth) ;
    lighting = !lighting ;
    glutPostRedisplay() ;
    break ;
 
A
d
d
i
n
g
 
V
i
s
u
a
l
 
D
e
t
a
i
l
 
Basic idea: use images instead of more
polygons to represent fine scale color variation
 
T
e
x
t
u
r
e
 
M
a
p
p
i
n
g
 
Important topic: nearly all objects textured
Wood grain, faces, bricks and so on
Adds visual detail to scenes
Can be added in a fragment shader
 
Polygonal model
 
With surface texture
 
S
e
t
t
i
n
g
 
u
p
 
t
e
x
t
u
r
e
 
inittexture("wood.ppm", shaderprogram) ;
 
// in init()
 
// Very basic code to read a ppm file
// And then set up buffers for texture coordinates
void inittexture (const char * filename, GLuint program) {
  int i,j,k ;
  FILE * fp ;
 
assert(fp = fopen(filename,"rb")) ;
   fscanf(fp,"%*s %*d %*d %*d%*c") ;
   for (i = 0 ; i < 256 ; i++)
     for (j = 0 ; j < 256 ; j++)
       for (k = 0 ; k < 3 ; k++)
 
 fscanf(fp,"%c",&(woodtexture[i][j][k])) ;
   fclose(fp) ;
 
T
e
x
t
u
r
e
 
C
o
o
r
d
i
n
a
t
e
s
 
Each vertex must have a texture coordinate: pointer to texture.
Interpolate for pixels (each fragment has st)
 
// Set up Texture Coordinates
   glGenTextures(1, texNames) ;
   
glBindVertexArray(VAOs[FLOOR]);
   glBindBuffer(GL_ARRAY_BUFFER, buffers[numobjects*numperobj+ncolors]) ;
   glBufferData(GL_ARRAY_BUFFER, sizeof (floortex),
floortex,GL_STATIC_DRAW);
 
 // Use layout location 2 for texcoords
   glEnableVertexAttribArray(2);
   glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0);
 
glActiveTexture(GL_TEXTURE0) ;
   glEnable(GL_TEXTURE_2D) ;
   glBindTexture (GL_TEXTURE_2D, texNames[0]) ;
 
S
p
e
c
i
f
y
i
n
g
 
t
h
e
 
T
e
x
t
u
r
e
 
I
m
a
g
e
 
glTexImage2D( target, level, components, width height,
border, format, type, data )
target is GL_TEXTURE_2D
level is (almost always) 0
components = 3 or 4 (RGB/RGBA)
width/height MUST be a power of 2
border = 0 (usually)
format = GL_RGB or GL_RGBA (usually)
type = GL_UNSIGNED_BYTE, GL_FLOAT, etc…
 
T
e
x
t
u
r
e
 
I
m
a
g
e
 
a
n
d
 
B
i
n
d
 
t
o
 
S
h
a
d
e
r
 
 glTexImage2D(GL_TEXTURE_2D,0,GL_RGB, 256, 256, 0, GL_RGB,
GL_UNSIGNED_BYTE, woodtexture) ;
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_LINEAR) ;
   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR) ;
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) ;
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) ;
 
   // Define a sampler.  See page 709 in red book, 7th ed.
   GLint texsampler ;
   texsampler = glGetUniformLocation(program, "tex") ;
   glUniform1i(texsampler,0) ; // Could also be GL_TEXTURE0
   istex = glGetUniformLocation(program,"istex") ;
 
D
r
a
w
i
n
g
 
w
i
t
h
 
T
e
x
t
u
r
e
 
 
// And a function to draw with textures, similar to drawobject
void drawtexture(GLuint object, GLuint texture) {
 
 
glBindTexture(GL_TEXTURE_2D, texture);
 
glBindVertexArray(VAOs[object]);
 
glDrawElements(PrimType[object], NumElems[object],
GL_UNSIGNED_BYTE, 0);
 
glBindVertexArray(0);
}
 
F
i
n
a
l
 
S
t
e
p
s
 
f
o
r
 
D
r
a
w
i
n
g
 
(
+
D
e
m
o
)
 
 
Vertex shader (just pass on texture coords)
layout (location = 2) in vec2 texCoords;
out vec2 texcoord; // similar definitions for positions and normals
uniform int istex ;
void main() {
    gl_Position = projection * modelview * vec4(position, 1.0f);
    mynormal = mat3(transpose(inverse(modelview))) * normal ;
    myvertex = modelview * vec4(position, 1.0f) ;
 
 texcoord = vec2 (0.0, 0.0); // Default value just to prevent errors
 
 if (istex != 0){ texcoord = texCoords;} }
Fragment shader (can be more complex blend)
uniform sampler2D tex ;
uniform int istex ;
void main (void) {
 
if (istex > 0) fragColor = texture(tex, texcoord) ;
 
 
 
 
M
o
r
e
 
o
n
 
T
e
x
t
u
r
e
 
(
v
e
r
y
 
b
r
i
e
f
l
y
)
 
Full lecture later in course
Optimizations for efficiency
Mipmapping
Filtering
Texture Coordinate generation
Texture Matrix
Environment Mapping
 
 
If very ambitious, read more in OpenGL
 
D
i
s
p
l
a
c
e
m
e
n
t
 
M
a
p
p
i
n
g
 
I
l
l
u
m
i
n
a
t
i
o
n
 
M
a
p
s
 
Quake introduced 
illumination maps
 
or 
light
maps
 to capture lighting effects in video games
 
Texture map:
 
Texture map
+ light map:
 
Light map
 
E
n
v
i
r
o
n
m
e
n
t
 
M
a
p
s
 
Images from 
Illumination and Reflection Maps:
                   Simulated Objects in Simulated and Real Environments
Gene Miller and C. Robert Hoffman
SIGGRAPH 1984 
Advanced Computer Graphics Animation
 Course Notes
 
S
o
l
i
d
 
t
e
x
t
u
r
e
s
 
Texture values indexed
by 3D location (x,y,z)
Expensive storage, or
Compute on the fly,
e.g. Perlin noise 
 
 
Slide Note
Embed
Share

This content covers a lecture on OpenGL basics related to computer graphics, including methodologies, demos, reviews, and geometry setup. It discusses topics such as shader programs, geometric objects, color rendering, and texture mapping. Get insights on implementing OpenGL concepts effectively for practical applications.

  • OpenGL
  • Computer Graphics
  • Lecture
  • Methodology
  • Demos

Uploaded on Mar 03, 2025 | 0 Views


Download Presentation

Please find below an Image/Link to download the presentation.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author.If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.

You are allowed to download the files provided on this website for personal or commercial use, subject to the condition that they are used lawfully. All files are the property of their respective owners.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author.

E N D

Presentation Transcript


  1. Computer Graphics CSE 167 [Win 17], Lecture 8: OpenGL 2 Ravi Ramamoorthi http://viscomp.ucsd.edu/classes/cse167/wi17

  2. To Do Continue working on HW 2. Can be difficult Class lectures, programs primary source Can leverage many sources (GL(SL) book, excellent online documentation, see links class website) It is a good idea to copy (and modify) relevant segments

  3. Methodology for Lecture Make mytest1 more ambitious Sequence of steps Demo

  4. Review of Last Demo Changed floor to all white, added global for teapot and teapotloc, moved geometry to new header file Demo 0 [set DEMO to 4 all features] #include <GL/glut.h> //also <GL/glew.h>; <GLUT/glut.h> for Mac OS #include shaders.h #include geometry.h int mouseoldx, mouseoldy ; // For mouse motion GLfloat eyeloc = 2.0 ; // Where to look from; initially 0 -2, 2 GLfloat teapotloc = -0.5 ; // ** NEW ** where the teapot is located GLint animate = 0 ; // ** NEW ** whether to animate or not GLuint vertexshader, fragmentshader, shaderprogram ; // shaders const int DEMO = 0 ; // ** NEW ** To turn on and off features

  5. Outline Review of demo from last lecture Basic geometry setup for cubes (pillars), colors Single geometric object, but multiple colors for pillars Matrix Stacks and Transforms (draw 4 pillars) Depth testing (Z-buffering) Animation (moving teapot) Texture Mapping (wooden floor) Best source for OpenGL is the red book and GLSL book. Of course, this is more a reference manual than a textbook, and you are better off implementing rather reading end to end.

  6. Geometry Basic Setup 1 const int numobjects = 2 ; // number of objects for buffer const int numperobj = 3 ; const int ncolors = 4 ; GLUint VAOs[numobjects+ncolors], teapotVAO; // VAO (Vertex Array Object) for each primitive object GLuint buffers[numperobj*numobjects+ncolors], teapotbuffers[3] ; ** NEW ** List of buffers for geometric data GLuint objects[numobjects] ; // ** NEW ** For each object GLenum PrimType[numobjects] ; GLsizei NumElems[numobjects] ; // // For the geometry of the teapot std::vector <glm::vec3> teapotVertices; std::vector <glm::vec3> teapotNormals; std::vector <unsigned int> teapotIndices; // To be used as a matrix stack for the modelview. std::vector <glm::mat4> modelviewStack;

  7. Geometry Basic Setup 2 // ** NEW ** Floor Geometry is specified with a vertex array // ** NEW ** Same for other Geometry enum {Vertices, Colors, Elements} ; // For arrays for object enum {FLOOR, CUBE} ; // For objects, for the floor const GLfloat floorverts[4][3] = { {0.5, 0.5, 0.0}, {-0.5, 0.5, 0.0}, {-0.5, -0.5, 0.0}, {0.5, -0.5, 0.0} } ; const GLfloat floorcol[4][3] = { {1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}, {1.0, 1.0, 1.0} } ; const GLubyte floorinds[1][6] = { {0, 1, 2, 0, 2, 3} } ; const GLfloat floortex[4][2] = { {1.0, 1.0}, {0.0, 1.0}, {0.0, 0.0}, {1.0, 0.0} } ;

  8. Cube geometry (for pillars) const GLfloat wd = 0.1 ; const GLfloat ht = 0.5 ; const GLfloat _cubecol[4][3] = { {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, {1.0, 1.0, 0.0} } ; const GLfloat cubeverts[8][3] = { {-wd, -wd, 0.0}, {-wd, wd, 0.0}, {wd, wd, 0.0}, {wd, -wd, 0.0}, {-wd, -wd, ht}, {wd, -wd, ht}, {wd, wd, ht}, {-wd, wd, ht} } ; GLfloat cubecol[12][3] ; const GLubyte cubeinds[12][3] = { {0, 1, 2}, {0, 2, 3}, // BOTTOM {4, 5, 6}, {4, 6, 7}, // TOP {0, 4, 7}, {0, 7, 1}, // LEFT {0, 3, 5}, {0, 5, 4}, // FRONT {3, 2, 6}, {3, 6, 5}, // RIGHT {1, 7, 6}, {1, 6, 2} // BACK } ;

  9. Initialize Geometry Function // This function takes in a vertex, color, index and type array void initobject(GLuint object, GLfloat * vert, GLint sizevert, GLfloat * col, GLint sizecol, GLubyte * inds, GLint sizeind, GLenum type) { int offset = object * numperobj ; glBindVertexArray(VAOs[object]); glBindBuffer(GL_ARRAY_BUFFER, buffers[Vertices + offset]); glBufferData(GL_ARRAY_BUFFER, sizevert, vert, GL_STATIC_DRAW); // Use layout location 0 for the vertices glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0); glBindBuffer(GL_ARRAY_BUFFER, buffers[Colors + offset]); glBufferData(GL_ARRAY_BUFFER, sizecol, col, GL_STATIC_DRAW); // Use layout location 1 for the colors glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[Elements + offset]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeind, inds, GL_STATIC_DRAW); PrimType[object] = type; NumElems[object] = sizeind; // Prevent further modification of this VAO by unbinding it glBindVertexArray(0);}

  10. Initialize Cubes with Colors 1 void initcubes(GLuint object, GLfloat * vert, GLint sizevert, GLubyte * inds, GLint sizeind, GLenum type) { for (int i = 0; i < ncolors; i++) { for (int j = 0; j < 8; j++) for (int k = 0; k < 3; k++) cubecol[j][k] = _cubecol[i][k]; glBindVertexArray(VAOs[object + i]); int offset = object * numperobj; int base = numobjects * numperobj; glBindBuffer(GL_ARRAY_BUFFER, buffers[Vertices + offset]); glBufferData(GL_ARRAY_BUFFER, sizevert, vert, GL_STATIC_DRAW); // Use layout location 0 for the vertices glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0); glBindBuffer(GL_ARRAY_BUFFER, buffers[base + i]); glBufferData(GL_ARRAY_BUFFER, sizeof(cubecol), cubecol, GL_STATIC_DRAW);

  11. Initialize Cubes with Colors 2 ... sizeof(GLfloat), 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[Elements + offset]); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeind, inds, GL_STATIC_DRAW); PrimType[object] = type; NumElems[object] = sizeind; // Prevent further modification of this VAO by unbinding it glBindVertexArray(0); } // Use layout location 1 for the colors glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * } //in init initobject(FLOOR, (GLfloat *) floorverts, sizeof(floorverts), (GLfloat *) floorcol, sizeof (floorcol), (GLubyte *) floorinds, sizeof (floorinds), GL_TRIANGLES) ; initcubes(CUBE, (GLfloat *)cubeverts, sizeof(cubeverts), (GLubyte *)cubeinds, sizeof(cubeinds), GL_TRIANGLES); loadteapot();

  12. Drawing with/without Colors // And a function to draw with them, similar to drawobject but with color void drawcolor(GLuint object, GLuint color) { glBindVertexArray(VAOs[object + color]); glDrawElements(PrimType[object], NumElems[object], GL_UNSIGNED_BYTE, 0); glBindVertexArray(0); } void drawobject(GLuint object) { glBindVertexArray(VAOs[object]); glDrawElements(PrimType[object], NumElems[object], GL_UNSIGNED_BYTE, 0); glBindVertexArray(0); } void loadteapot() // See source code for details if interested

  13. Outline Review of demo from last lecture Basic geometry setup for cubes (pillars), colors Single geometric object, but multiple colors for pillars Matrix Stacks and Transforms (draw 4 pillars) Depth testing (Z-buffering) Animation (moving teapot) Texture Mapping (wooden floor) Best source for OpenGL is the red book and GLSL book. Of course, this is more a reference manual than a textbook, and you are better off implementing rather reading end to end.

  14. Summary OpenGL Vertex Transforms Clip coordinates Perspective Divide (Dehomogenization) Object coords (x y z w)t vertex Normalized Device Coordinates Modelview matrix [Object Transforms and glm::lookAt] Viewport Transform (glViewport) Eye coordinates (used for lighting) Window Coords Projection matrix [3D to 2D, usually glm::perspective]

  15. Transformations Matrix Stacks Old OpenGL: glPushMatrix, glPopMatrix, glLoad, glMultMatrixf Useful for hierarchically defined figures, placing pillars Current recommendation is STL stacks managed yourself, which is done in mytest2. (You must manage the stack yourself for HW 2). Transforms Write your own translate, scale, rotate for HW 1 and HW 2 Careful of OpenGL convention: In old-style, Right-multiply current matrix (last is first applied). glm operators follow this sometimes. Also gluLookAt (glm::lookAt), gluPerspective (glm::perspective) Remember just matrix like any other transform, affecting modelview See mytest for how to best implement these ideas

  16. Drawing Pillars 1 (in display) // 1st pillar: Right-multiply modelview as in old OpenGL pushMatrix(modelview) ; // push/pop functions for stack modelview = modelview * glm::translate(identity, glm::vec3(-0.4, - 0.4, 0.0)) ; // build translation matrix glUniformMatrix4fv(modelviewPos, 1, GL_FALSE, &(modelview)[0][0]); drawcolor(CUBE, 0) ; popMatrix(modelview) ; // 2nd pillar pushMatrix(modelview) ; modelview = modelview * glm::translate(identity, glm::vec3(0.4, - 0.4, 0.0)) ; // build translation matrix glUniformMatrix4fv(modelviewPos, 1, GL_FALSE, &(modelview)[0][0]); drawcolor(CUBE, 1) ; popMatrix(modelview) ; // Function pushes specified matrix onto the modelview stack void pushMatrix(glm::mat4 mat) {

  17. Drawing Pillars 2 // 3rd pillar pushMatrix(modelview); modelview = modelview * glm::translate(identity, glm::vec3(0.4, 0.4, 0.0)); glUniformMatrix4fv(modelviewPos, 1, GL_FALSE, &(modelview)[0][0]); drawcolor(CUBE, 2) ; popMatrix(modelview); // 4th pillar pushMatrix(modelview); modelview = modelview * glm::translate(identity, glm::vec3(- 0.4, 0.4, 0.0)); glUniformMatrix4fv(modelviewPos, 1, GL_FALSE, &(modelview)[0][0]); drawcolor(CUBE, 3) ; popMatrix(modelview); // This function pops a matrix from the modelview stack void popMatrix(glm::mat4& mat) { if (modelviewStack.size()) { mat = glm::mat4(modelviewStack.back()); modelviewStack.pop_back(); } else { // Just to prevent errors when popping from an empty

  18. Demo Demo 1 Does order of drawing matter? What if I move floor after pillars in code? Is this desirable? If not, what can I do about it?

  19. Outline Review of demo from last lecture Basic geometry setup for cubes (pillars), colors Single geometric object, but multiple colors for pillars Matrix Stacks and Transforms (draw 4 pillars) Depth testing (Z-buffering) Animation (moving teapot) Texture Mapping (wooden floor) Best source for OpenGL is the red book and GLSL book. Of course, this is more a reference manual than a textbook, and you are better off implementing rather reading end to end.

  20. Double Buffering New primitives draw over (replace) old objects Can lead to jerky sensation Solution: double buffer. Render into back (offscreen) buffer. When finished, swap buffers to display entire image at once. Changes in main and display glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutSwapBuffers() ; glFlush ();

  21. Turning on Depth test (Z-buffer) OpenGL uses a Z-buffer for depth tests For each pixel, store nearest Z value (to camera) so far If new fragment is closer, it replaces old z, color [ less than can be over-ridden in fragment program] Simple technique to get accurate visibility (Be sure you know what fragments and pixels are) Changes in main fn, display to Z-buffer glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); In init function glEnable(GL_DEPTH_TEST) ; glDepthFunc(GL_LESS) ; // The default option

  22. Demo Demo 2 Does order of drawing matter any more? What if I change near plane to 0? Is this desirable? If not, what can I do about it?

  23. Outline Review of demo from last lecture Basic geometry setup for cubes (pillars), colors Single geometric object, but multiple colors for pillars Matrix Stacks and Transforms (draw 4 pillars) Depth testing (Z-buffering) Animation (moving teapot) Texture Mapping (wooden floor) Best source for OpenGL is the red book and GLSL book. Of course, this is more a reference manual than a textbook, and you are better off implementing rather reading end to end.

  24. Demo Demo 3 Notice how teapot cycles around And that I can pause and restart animation And do everything else (zoom etc.) while teapot moves in background

  25. Drawing Teapot (in display) // ** NEW ** Put a teapot in the middle that animates pushMatrix(modelview); modelview = modelview * glm::translate(identity, glm::vec3(teapotloc, 0.0, 0.0)); // The following two transforms set up and center the teapot // Transforms right-multiply the modelview matrix (top of the stack) modelview = modelview * glm::translate(identity, glm::vec3(0.0, 0.0, 0.1)); modelview = modelview * glm::rotate(identity, glm::pi<float>() / 2.0f, glm::vec3(1.0, 0.0, 0.0)); float size = 0.235f; // Teapot size modelview = modelview * glm::scale(identity, glm::vec3(size, size, size)); glUniformMatrix4fv(modelviewPos, 1, GL_FALSE, &(modelview)[0][0]); drawteapot() ; popMatrix(modelview); void drawteapot() {// drawteapot() function in geometry.h glBindVertexArray(teapotVAO); glDrawElements(GL_TRIANGLES, teapotIndices.size(), GL_UNSIGNED_INT, 0); glBindVertexArray(0); }

  26. Simple Animation routine // ** NEW ** in this assignment, is an animation of a teapot // Hitting p will pause this animation; see keyboard callback void animation(void) { teapotloc = teapotloc + 0.005 ; if (teapotloc > 0.5) teapotloc = -0.5 ; glutPostRedisplay() ; }

  27. Keyboard callback (p to pause) GLint animate = 0 ; // ** NEW ** whether to animate or not void keyboard (unsigned char key, int x, int y) { switch (key) { case 27: // Escape to quit exit(0) ; break ; case 'p': // ** NEW ** to pause/restart animation animate = !animate ; if (animate) glutIdleFunc(animation) ; else glutIdleFunc(NULL) ; break ; default: break ; } }

  28. Outline Review of demo from last lecture Display lists (extend init for pillars) Matrix stacks and transforms (draw 4 pillars) Depth testing or z-buffering Animation (moving teapot) Texture mapping (wooden floor) [mytest3]

  29. New globals and basic setup // In mytest3.cpp GLubyte woodtexture[256][256][3] ; // texture (from grsites.com) GLuint texNames[1] ; // texture buffer GLuint istex ; // blend parameter for texturing GLuint islight ; // for lighting GLint texturing = 1 ; // to turn on/off texturing GLint lighting = 1 ; // to turn on/off lighting // In Display glUniform1i(islight,0) ; // Turn off lighting (except on teapot, later) glUniform1i(istex,texturing) ; drawtexture(FLOOR,texNames[0]) ; // Texturing floor // drawobject(FLOOR) ; glUniform1i(istex,0) ; // Other items aren't textured

  30. Simple Toggles for Keyboard case 't': // ** NEW ** to turn on/off texturing ; texturing = !texturing ; glutPostRedisplay() ; break ; case 's': // ** NEW ** to turn on/off shading (always smooth) ; lighting = !lighting ; glutPostRedisplay() ; break ;

  31. Adding Visual Detail Basic idea: use images instead of more polygons to represent fine scale color variation

  32. Texture Mapping Important topic: nearly all objects textured Wood grain, faces, bricks and so on Adds visual detail to scenes Can be added in a fragment shader Polygonal model With surface texture

  33. Setting up texture inittexture("wood.ppm", shaderprogram) ; // in init() // Very basic code to read a ppm file // And then set up buffers for texture coordinates void inittexture (const char * filename, GLuint program) { int i,j,k ; FILE * fp ; assert(fp = fopen(filename,"rb")) ; fscanf(fp,"%*s %*d %*d %*d%*c") ; for (i = 0 ; i < 256 ; i++) for (j = 0 ; j < 256 ; j++) for (k = 0 ; k < 3 ; k++) fscanf(fp,"%c",&(woodtexture[i][j][k])) ; fclose(fp) ;

  34. Texture Coordinates Each vertex must have a texture coordinate: pointer to texture. Interpolate for pixels (each fragment has st) // Set up Texture Coordinates glGenTextures(1, texNames) ; glBindVertexArray(VAOs[FLOOR]); glBindBuffer(GL_ARRAY_BUFFER, buffers[numobjects*numperobj+ncolors]) ; glBufferData(GL_ARRAY_BUFFER, sizeof (floortex), floortex,GL_STATIC_DRAW); // Use layout location 2 for texcoords glEnableVertexAttribArray(2); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0); glActiveTexture(GL_TEXTURE0) ; glEnable(GL_TEXTURE_2D) ; glBindTexture (GL_TEXTURE_2D, texNames[0]) ;

  35. Specifying the Texture Image glTexImage2D( target, level, components, width height, border, format, type, data ) target is GL_TEXTURE_2D level is (almost always) 0 components = 3 or 4 (RGB/RGBA) width/height MUST be a power of 2 border = 0 (usually) format = GL_RGB or GL_RGBA (usually) type = GL_UNSIGNED_BYTE, GL_FLOAT, etc

  36. Texture Image and Bind to Shader glTexImage2D(GL_TEXTURE_2D,0,GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, woodtexture) ; glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) ; glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) ; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) ; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) ; // Define a sampler. See page 709 in red book, 7th ed. GLint texsampler ; texsampler = glGetUniformLocation(program, "tex") ; glUniform1i(texsampler,0) ; // Could also be GL_TEXTURE0 istex = glGetUniformLocation(program,"istex") ;

  37. Drawing with Texture // And a function to draw with textures, similar to drawobject void drawtexture(GLuint object, GLuint texture) { glBindTexture(GL_TEXTURE_2D, texture); glBindVertexArray(VAOs[object]); glDrawElements(PrimType[object], NumElems[object], GL_UNSIGNED_BYTE, 0); glBindVertexArray(0); }

  38. Final Steps for Drawing (+Demo) Vertex shader (just pass on texture coords) layout (location = 2) in vec2 texCoords; out vec2 texcoord; // similar definitions for positions and normals uniform int istex ; void main() { gl_Position = projection * modelview * vec4(position, 1.0f); mynormal = mat3(transpose(inverse(modelview))) * normal ; myvertex = modelview * vec4(position, 1.0f) ; texcoord = vec2 (0.0, 0.0); // Default value just to prevent errors Fragment shader (can be more complex blend) if (istex != 0){ texcoord = texCoords;} } uniform sampler2D tex ; uniform int istex ; void main (void) { if (istex > 0) fragColor = texture(tex, texcoord) ;

  39. More on Texture (very briefly) Full lecture later in course Optimizations for efficiency Mipmapping Filtering Texture Coordinate generation Texture Matrix Environment Mapping If very ambitious, read more in OpenGL

  40. Displacement Mapping

  41. Illumination Maps Quake introduced illumination maps or light maps to capture lighting effects in video games Texture map: Light map Texture map + light map:

  42. Environment Maps Images from Illumination and Reflection Maps: Simulated Objects in Simulated and Real Environments Gene Miller and C. Robert Hoffman SIGGRAPH 1984 Advanced Computer Graphics Animation Course Notes

  43. Solid textures Texture values indexed by 3D location (x,y,z) Expensive storage, or Compute on the fly, e.g. Perlin noise

More Related Content

giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#