3D Graphics Programming with QuickDraw 3D
_New
function for the type of illumination model you want to use. For example, to use Phong illumination, you can call the Q3PhongIllumination_New
function.
Once you've created an illumination shader, you apply it to the objects in a model by submitting the shader inside of a submitting loop, or by adding it to a group that is submitted in a submitting loop. For instance, to apply Phong illumination to all the objects in a model, you can call the function Q3Shader_Submit
in your rendering loop, as shown in Listing 14-1.
Listing 14-1 Applying an illumination shader
Q3View_StartRendering(myView); do { Q3Shader_Submit(myPhongShader, myView); /*submit styles, groups, and other objects here*/ myViewStatus = Q3View_EndRendering(myView); } while (myViewStatus == kQ3ViewStatusRetraverse);
Q3TextureShader_New
function, to which you pass a texture object. QuickDraw3D currently supports only pixmap texture objects, which you create by calling the Q3PixMapTexture_New
function.Once you've created a texture shader, you can apply it to all the objects in a model by submitting the shader inside of a rendering loop, as shown in Listing 14-2.
Listing 14-2 Applying a texture shader in a submitting loop
Q3View_StartRendering(myView); do { Q3Shader_Submit(myTextureShader, myView); /*submit styles, groups, and other objects here*/ myViewStatus = Q3View_EndRendering(myView); } while (myViewStatus == kQ3ViewStatusRetraverse);You can apply the shader to the objects in a group by adding it to a group that is submitted in a rendering loop, as shown in Listing 14-3. (The
myGroup
group is an ordered display group.)Listing 14-3 Applying a texture shader in a group
Q3Group_AddObject(myGroup, myTextureShader); Q3View_StartRendering(myView); do { Q3Group_Submit(myGroup, myView); myViewStatus = Q3View_EndRendering(myView); } while (myViewStatus == kQ3ViewStatusRetraverse);You can also apply a texture shader to all the objects in a model by adding the shader as an attribute of type
kQ3AttributeTypeSurfaceShader
to the view's attribute set. Similarly, you can attach the texture shader to a part of a geometric object as an attribute. For example, you can attach a texture shader to the face of a cube or a mesh to have that face shaded with a texture. Listing 14-4 illustrates how to create a texture shader and use it to shade a triangle. Note that the function MyCreateShadedTriangle
defined in Listing 14-4 sets up a custom surface parameterization for the triangle, because there is no standard surface parameterization for a triangle.Listing 14-4 Applying a texture shader as an attribute
TQ3GeometryObject MyCreateShadedTriangle (TQ3StoragePixmap myPixmap) { TQ3ShaderObject myShader; TQ3TextureObject myTexture; TQ3TriangleData myTriData; TQ3GeometryObject myTriangle; TQ3Param2D myParam2D; TQ3Vertex3D myVertices[3] = { { { 0.5, 0.5, 0.0}, NULL }, { {-0.5, 0.5, 0.0}, NULL }, { {-0.5, -0.5, 0.0}, NULL }}; /*Create a new texture from the pixmap passed in.*/ myTexture = Q3PixmapTexture_New(&myPixmap); if (myTexture == NULL) return (NULL); Q3Object_Dispose(myPixmap.image); /*Create a new texture shader from the texture.*/ myShader = Q3TextureShader_New(myTexture); if (myShader == NULL) return (NULL); Q3Object_Dispose(myTexture); /*Configure triangle data.*/ /*First, attach uv values to the three vertices.*/ myParam2D.u = 0; myParam2D.v = 0; myVertices[0].attributeSet = Q3AttributeSet_New(); Q3AttributeSet_Add(myVertices[0].attributeSet, kQ3AttributeTypeShadingUV, &myParam2D); myParam2D.u = 0; myParam2D.v = 1; myVertices[1].attributeSet = Q3AttributeSet_New(); Q3AttributeSet_Add(myVertices[1].attributeSet, kQ3AttributeTypeShadingUV, &myParam2D); myParam2D.u = 1; myParam2D.v = 1; myVertices[2].attributeSet = Q3AttributeSet_New(); Q3AttributeSet_Add(myVertices[2].attributeSet, kQ3AttributeTypeShadingUV, &myParam2D); /*Define the triangle, using the vertices and uv values just set up.*/ myTriData.vertices[0] = myVertices[0]; myTriData.vertices[1] = myVertices[1]; myTriData.vertices[2] = myVertices[2]; /*Attach a texture surface shader as an attribute.*/ myTriData.triangleAttributeSet = Q3AttributeSet_New(); Q3AttributeSet_Add(myTriData.triangleAttributeSet, kQ3AttributeTypeSurfaceShader, &myShader); myTriangle = Q3Triangle_New(&myTriData); Q3Object_Dispose(myVertices[0].attributeSet); Q3Object_Dispose(myVertices[1].attributeSet); Q3Object_Dispose(myVertices[2].attributeSet); return(myTriangle); }The function
MyCreateShadedTriangle
defined in Listing 14-4 creates a texture from the pixmap it is passed and then creates a new texture shader from that texture. MyCreateShadedTriangle
then attaches uv parameterization values to each of the three triangle vertices and defines the triangle data. Finally, MyCreateShadedTriangle
creates a triangle and returns it to its caller. When the triangle is drawn (perhaps by being submitted in a rendering loop), it will have the specified texture mapped onto it.Q3PixmapTexture_New
function (as in Listing 14-4 on page 1412) is a storage pixmap, of type TQ3StoragePixmap
. The image
field Q3MemoryStorage_New
or Q3MemoryStorage_NewBuffer
to create a storage object. Which function you use depends on whether (1) you want QuickDraw3D to maintain the image data in an internal buffer or (2) you want to maintain the data in your
To let QuickDraw3D manage the pixmap data, you can assign the image
field of a storage pixmap using code like this:
myStoragePixmap.image = Q3MemoryStorage_New(myBuffer, mySize);This code asks QuickDraw3D to allocate a buffer internally, of the specified size. Once
Q3MemoryStorage_New
returns successfully, you can dispose of the buffer myBuffer
, because QuickDraw3D has copied the texture pixmap data into its own internal memory.
If you prefer, you can maintain the pixmap data in your application's memory partition and avoid the overhead of having the data copied to internal QuickDraw3D memory. (This is especially useful if you want to animate a texture by changing the texture pixmap data from frame to frame.) To do this, you create a storage object by calling the Q3MemoryStorage_NewBuffer
function, like this:
myStoragePixmap.image = Q3MemoryStorage_NewBuffer (myBuffer, mySize, mySize);In this case, you should not dispose of the data buffer. You can change the pixmap data by calling
Q3MemoryStorage_SetBuffer
.
Q3MemoryStorage_SetBuffer
(myStoragePixmap.image, myBuffer, mySize, mySize);
You need to call Q3MemoryStorage_SetBuffer
to force QuickDraw3D to update any caches.
You can also change the data of a storage object created by a call to Q3MemoryStorage_New
, by calling Q3MemoryStorage_Set
.<8bat>u
Currently, QuickDraw3D supports two boundary-handling methods: wrapping and clamping. To wrap a shader effect is to replicate the entire effect across the mapped area. For example, to wrap a texture is to replicate the texture across the entire mapped area, as many times as are necessary to fill the mapped area. To clamp a shader effect is to replicate the boundaries of the effect across the portion of the mapped area that lies outside the valid range 0.0 to 1.0.
You can specify the boundary-handling methods of the u and v directions independently. You can call the Q3Shader_SetUBoundary
function to indicate how to handle values in the u parametric direction that lie outside the valid range, and you can call the Q3Shader_SetVBoundary
function to indicate how to handle values in the v parametric direction that lie outside the valid range. The default boundary-handling method is to wrap in both the u and v parametric directions.
Let us know what you think of these prototype pages.
Generated with Harlequin WebMaker