Last active
May 17, 2022 06:14
-
-
Save Pokechu22/0589a46b2dea081e24470b3275766cc0 to your computer and use it in GitHub Desktop.
Embossing demo (based on lesson08)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<filepath="Dolphin-height-tex.bmp" id="heighttex" colfmt=3 /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define SUPPLY_BINORMALS true | |
#define USE_CYLINDER true | |
#define USE_LINEAR_FILTERING true | |
/*--------------------------------------------------------------------------------- | |
nehe lesson 8 port to GX by shagkur | |
---------------------------------------------------------------------------------*/ | |
#include <vector> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <malloc.h> | |
#include <math.h> | |
#include <gccore.h> | |
#include <wiiuse/wpad.h> | |
#include "heighttex_tpl.h" | |
#include "heighttex.h" | |
#define DEFAULT_FIFO_SIZE (256*1024) | |
typedef struct tagtexdef | |
{ | |
void *pal_data; | |
void *tex_data; | |
u32 sz_x; | |
u32 sz_y; | |
u32 fmt; | |
u32 min_lod; | |
u32 max_lod; | |
u32 min; | |
u32 mag; | |
u32 wrap_s; | |
u32 wrap_t; | |
void *nextdef; | |
} texdef; | |
static GXColor litcolors_main[] = { | |
{ 0x40, 0x40, 0x40, 0xFF }, // Light color 1 | |
{ 0x80, 0x80, 0x80, 0xFF }, // Ambient 1 | |
{ 0xFF, 0xFF, 0xFF, 0xFF } // Material 1 | |
}; | |
static GXColor litcolors_aux[] = { | |
{ 0xFF, 0xFF, 0xFF, 0xFF }, // Light color 1 | |
{ 0x10, 0x10, 0x10, 0xFF }, // Ambient 1 | |
{ 0xFF, 0xFF, 0xFF, 0xFF } // Material 1 | |
}; | |
static GXRModeObj *rmode = NULL; | |
static void *frameBuffer[2] = { NULL, NULL}; | |
void setlight(Mtx view,guVector dir, GXColor litcol, GXColor ambcol,GXColor matcol) | |
{ | |
guVector lpos; | |
GXLightObj lobj; | |
guVecScale(&dir, &lpos, 10000.0f); | |
guVecMultiply(view,&lpos,&lpos); | |
GX_InitLightPos(&lobj,lpos.x,lpos.y,lpos.z); | |
GX_InitLightColor(&lobj,litcol); | |
GX_LoadLightObj(&lobj,GX_LIGHT0); | |
// set number of rasterized color channels | |
GX_SetNumChans(1); | |
GX_SetChanCtrl(GX_COLOR0A0,GX_ENABLE,GX_SRC_REG,GX_SRC_REG,GX_LIGHT0,GX_DF_CLAMP,GX_AF_NONE); | |
GX_SetChanAmbColor(GX_COLOR0A0,ambcol); | |
GX_SetChanMatColor(GX_COLOR0A0,matcol); | |
} | |
void setnolight() | |
{ | |
GX_SetNumChans(1); | |
GX_SetChanCtrl(GX_COLOR0A0,GX_DISABLE,GX_SRC_REG,GX_SRC_VTX,GX_LIGHTNULL,GX_DF_CLAMP,GX_AF_NONE); | |
} | |
struct Vertex | |
{ | |
guVector pos; | |
guVector normal; | |
guVector tangent; | |
guVector binormal; | |
f32 u, v; | |
}; | |
inline void WriteVec(guVector vec) | |
{ | |
// Note that GX_Position3f32 and GX_Normal3f32 are internally the exact same thing | |
GX_Position3f32(vec.x, vec.y, vec.z); | |
} | |
std::vector<Vertex> get_square() | |
{ | |
std::vector<Vertex> result; | |
for (f32 x = -1; x <= 1; x += 2) | |
{ | |
for (f32 y = -1; y <= 1; y += 2) | |
{ | |
auto& vtx = result.emplace_back(); | |
vtx.pos = {x, y, 1.0f}; | |
vtx.normal = {0.0f, 0.0f, 1.0f}; | |
vtx.tangent = {1.0f, 0.0f, 0.0f}; | |
vtx.binormal = {0.0f, -1.0f, 0.0f}; | |
vtx.u = (x + 1) / 2; | |
vtx.v = 1 - (y + 1) / 2; | |
} | |
} | |
return result; | |
} | |
std::vector<Vertex> get_half_cylinder(int num_quads) | |
{ | |
std::vector<Vertex> result; | |
for (int i = 0; i <= num_quads; i++) | |
{ | |
for (f32 y = -1; y <= 1; y += 2) | |
{ | |
f32 angle = M_PI * i / (f32) num_quads; | |
f32 x = -cosf(angle); | |
f32 z = sinf(angle); | |
auto& vtx = result.emplace_back(); | |
vtx.pos = {x, y, z}; | |
// Since we're using a unit radius, x^2 + z^2 is 1, so this is a unit vector. | |
vtx.normal = {x, 0.0f, z}; | |
// This works because the derivative of sin(t) is cos(t) and cos(t) is -sin(t) | |
vtx.tangent = {z, 0.0f, -x}; | |
// Since this is a cylinder (and not a sphere) we can use the same binormal for everything | |
vtx.binormal = {0.0f, -1.0f, 0.0f}; | |
vtx.u = i / (f32)num_quads; | |
vtx.v = 1 - (y + 1) / 2; | |
} | |
} | |
return result; | |
} | |
std::vector<Vertex> get_sphere(int num_subdivisions, f32 x_orig, f32 y_orig, f32 z_orig, f32 scale) | |
{ | |
std::vector<Vertex> result; | |
for (int y = 0; y < num_subdivisions; y++) | |
{ | |
for (int x = 0; x <= num_subdivisions; x++) | |
{ | |
for (int yoff = 0; yoff <= 1; yoff++) | |
{ | |
f32 angle_y = M_PI * (y + yoff) / (f32) num_subdivisions; | |
f32 sin_y = sinf(angle_y); | |
f32 pos_y = cosf(angle_y); | |
f32 angle_x = M_PI * x / (f32) num_subdivisions; | |
f32 pos_x = cosf(angle_x) * sin_y; | |
f32 pos_z = sinf(angle_x) * sin_y; | |
auto& vtx = result.emplace_back(); | |
vtx.pos = {x_orig + pos_x*scale, y_orig + pos_y*scale, z_orig + pos_z*scale}; | |
// This is just how spheres work. pos_x^2 + pos_y^2 + pos_z^2 = 1. | |
vtx.normal = {pos_x, pos_y, pos_z}; | |
// TODO: tangent and binormal - for now I'm just using this for other purposes | |
vtx.tangent = {0, 0, 0}; | |
vtx.binormal = {0, 0, 0}; | |
// TODO: uv - same deal | |
vtx.u = 0; | |
vtx.v = 0; | |
} | |
} | |
} | |
return result; | |
} | |
int main(int argc,char **argv) | |
{ | |
f32 yscale,zt = 0; | |
u32 xfbHeight; | |
u32 fb = 0; | |
u32 first_frame = 1; | |
GXTexObj texture; | |
Mtx view,mvi; // view and perspective matrices | |
Mtx model, modelview; | |
Mtx44 perspective; | |
void *gpfifo = NULL; | |
GXColor background = {0, 0, 0, 0xff}; | |
guVector cam = {0.0F, 0.0F, 0.0F}, | |
up = {0.0F, 1.0F, 0.0F}, | |
look = {0.0F, 0.0F, -1.0F}; | |
TPLFile heightTPL; | |
VIDEO_Init(); | |
WPAD_Init(); | |
rmode = VIDEO_GetPreferredMode(NULL); | |
// allocate the fifo buffer | |
gpfifo = memalign(32,DEFAULT_FIFO_SIZE); | |
memset(gpfifo,0,DEFAULT_FIFO_SIZE); | |
// allocate 2 framebuffers for double buffering | |
frameBuffer[0] = SYS_AllocateFramebuffer(rmode); | |
frameBuffer[1] = SYS_AllocateFramebuffer(rmode); | |
// configure video | |
VIDEO_Configure(rmode); | |
VIDEO_SetNextFramebuffer(frameBuffer[fb]); | |
VIDEO_Flush(); | |
VIDEO_WaitVSync(); | |
if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync(); | |
fb ^= 1; | |
// init the flipper | |
GX_Init(gpfifo,DEFAULT_FIFO_SIZE); | |
// clears the bg to color and clears the z buffer | |
GX_SetCopyClear(background, 0x00ffffff); | |
// other gx setup | |
GX_SetViewport(0,0,rmode->fbWidth,rmode->efbHeight,0,1); | |
yscale = GX_GetYScaleFactor(rmode->efbHeight,rmode->xfbHeight); | |
xfbHeight = GX_SetDispCopyYScale(yscale); | |
GX_SetScissor(0,0,rmode->fbWidth,rmode->efbHeight); | |
GX_SetDispCopySrc(0,0,rmode->fbWidth,rmode->efbHeight); | |
GX_SetDispCopyDst(rmode->fbWidth,xfbHeight); | |
GX_SetCopyFilter(rmode->aa,rmode->sample_pattern,GX_TRUE,rmode->vfilter); | |
GX_SetFieldMode(rmode->field_rendering,((rmode->viHeight==2*rmode->xfbHeight)?GX_ENABLE:GX_DISABLE)); | |
if (rmode->aa) { | |
GX_SetPixelFmt(GX_PF_RGB565_Z16, GX_ZC_LINEAR); | |
} else { | |
GX_SetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR); | |
} | |
GX_SetCullMode(GX_CULL_NONE); | |
GX_CopyDisp(frameBuffer[fb],GX_TRUE); | |
GX_SetDispCopyGamma(GX_GM_1_0); | |
GX_InvVtxCache(); | |
// Note: since we need to change the vertex descriptor as well, | |
// there isn't much benefit to defining multiple VATs | |
// (but we do need separate ones for when we include normal+tangent+binormal | |
// vs when we include only normals, so we might as well do this) | |
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); | |
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_NBT, GX_NRM_NBT, GX_F32, 0); | |
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); | |
GX_SetVtxAttrFmt(GX_VTXFMT1, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); | |
GX_SetVtxAttrFmt(GX_VTXFMT1, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0); | |
GX_SetVtxAttrFmt(GX_VTXFMT1, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0); | |
GX_SetVtxAttrFmt(GX_VTXFMT2, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); | |
GX_SetVtxAttrFmt(GX_VTXFMT2, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); | |
GX_SetVtxAttrFmt(GX_VTXFMT3, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); | |
GX_SetVtxAttrFmt(GX_VTXFMT3, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0); | |
// setup texture coordinate generation | |
// args: texcoord slot 0-7, matrix type, source to generate texture coordinates from, matrix to use | |
GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_TEX0, GX_IDENTITY); | |
GX_SetTexCoordGen(GX_TEXCOORD1, GX_TG_BUMP0, GX_TG_TEXCOORD0, GX_IDENTITY); | |
f32 w = rmode->viWidth; | |
f32 h = rmode->viHeight; | |
GX_InvalidateTexAll(); | |
TPL_OpenTPLFromMemory(&heightTPL, (void *)heighttex_tpl,heighttex_tpl_size); | |
TPL_GetTexture(&heightTPL,heighttex,&texture); | |
GX_InitTexObjFilterMode(&texture, USE_LINEAR_FILTERING ? GX_LINEAR : GX_NEAR, USE_LINEAR_FILTERING ? GX_LINEAR : GX_NEAR); | |
f32 tex_width = GX_GetTexObjWidth(&texture); | |
// setup our camera at the origin | |
// looking down the -z axis with y up | |
guLookAt(view, &cam, &up, &look); | |
// setup our projection matrix | |
// this creates a perspective matrix with a view angle of 90, | |
// and aspect ratio based on the display resolution | |
guPerspective(perspective, 45, (f32)w/h, 0.1F, 300.0F); | |
GX_LoadProjectionMtx(perspective, GX_PERSPECTIVE); | |
int framenum = 0; | |
GX_SetBlendMode(GX_BM_NONE, GX_BL_SRCALPHA, GX_BL_ONE, GX_LO_SET); | |
GX_SetColorUpdate(GX_TRUE); | |
GX_SetAlphaUpdate(GX_TRUE); | |
while(1) { | |
WPAD_ScanPads(); | |
if(WPAD_ButtonsDown(0) & WPAD_BUTTON_HOME) exit(0); | |
else if (WPAD_ButtonsHeld(0)&WPAD_BUTTON_UP) zt -= 0.25f; | |
else if (WPAD_ButtonsHeld(0)&WPAD_BUTTON_DOWN) zt += 0.25f; | |
framenum = (framenum + 1) % 900; | |
f32 angle, angle2; | |
if (framenum < 300) | |
{ | |
angle = framenum * M_PI / 60.f; | |
angle2 = .5f * M_PI * sinf(framenum * M_PI / 300.f); | |
} | |
else | |
{ | |
if (framenum < 450) | |
angle = 0; | |
else if (framenum < 600) | |
angle = M_PI; | |
else if (framenum < 750) | |
angle = .5f * M_PI; | |
else | |
angle = 1.5f * M_PI; | |
angle2 = .5f * M_PI * (1 - cosf(framenum * M_PI / 150.f)); | |
} | |
f32 dx = cosf(angle) * sinf(angle2); | |
f32 dy = sinf(angle) * sinf(angle2); | |
f32 dz2 = 1 - dx*dx - dy*dy; // dx^2 + dy^2 + dz^2 = 1 for a unit-length vector | |
f32 dz = dz2 > 0 ? sqrtf(dz2) : 0; // Avoid NaN issues | |
guVector ldir = {dx, dy, dz}; | |
// set number of rasterized color channels | |
setlight(view, ldir, litcolors_main[0],litcolors_main[1],litcolors_main[2]); | |
//set number of textures to generate | |
GX_SetNumTexGens(2); | |
// These TEV stages are set up to match RS2 (x-wing 1). | |
GX_SetNumTevStages(3); | |
GX_LoadTexObj(&texture, GX_TEXMAP0); | |
GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); | |
GX_SetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_FALSE, GX_TEVPREV); | |
GX_SetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXA, GX_CC_RASC, GX_CC_RASC); | |
GX_SetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP0, GX_COLOR0A0); | |
GX_SetTevColorOp(GX_TEVSTAGE1, GX_TEV_SUB, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVREG1); | |
GX_SetTevColorIn(GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_TEXA, GX_CC_RASC, GX_CC_CPREV); | |
GX_SetTevOrder(GX_TEVSTAGE2, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); | |
GX_SetTevColorOp(GX_TEVSTAGE2, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); | |
GX_SetTevColorIn(GX_TEVSTAGE2, GX_CC_ZERO, GX_CC_TEXC, GX_CC_C1, GX_CC_ZERO); | |
guMtxIdentity(model); | |
//guVector cubeAxis = {1,1,1}; | |
//guMtxRotAxisDeg(model, &cubeAxis, 45.f); | |
guMtxTransApply(model, model, 0.0f,0.0f,zt-4.0f); | |
guMtxConcat(view,model,modelview); | |
// load the modelview matrix into matrix memory | |
GX_LoadPosMtxImm(modelview, GX_PNMTX0); | |
guMtxInverse(modelview,mvi); | |
guMtxTranspose(mvi,modelview); | |
guMtxScaleApply(modelview, mvi, 1.f/tex_width, 1.f/tex_width, 1.f/tex_width); | |
GX_LoadNrmMtxImm(mvi, GX_PNMTX0); | |
auto vertices = USE_CYLINDER ? get_half_cylinder(4) : get_square(); | |
guVector fake_tangent = {1.0f, 0.0f, 0.0f}; | |
guVector fake_binormal = {0.0f, -1.0f, 0.0f}; | |
if (!SUPPLY_BINORMALS) | |
{ | |
GX_ClearVtxDesc(); | |
GX_SetVtxDesc(GX_VA_POS, GX_DIRECT); | |
GX_SetVtxDesc(GX_VA_NBT, GX_DIRECT); | |
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT); | |
// We don't want the point we draw to set the cached tangent and binormal | |
// to actually draw to the screen | |
GX_SetCullMode(GX_CULL_ALL); | |
GX_Begin(GX_POINTS, GX_VTXFMT0, 1); | |
GX_Position3f32(0, 0, 0); // Arbitrary (as long as it's not clipped/determined to be off screen) | |
GX_Normal3f32(0, 0, 1); // Arbitrary | |
GX_Normal3f32(fake_tangent.x, fake_tangent.y, fake_tangent.z); | |
GX_Normal3f32(fake_binormal.x, fake_binormal.y, fake_binormal.z); | |
GX_TexCoord2f32(0, 0); // Arbitrary | |
GX_End(); | |
GX_SetCullMode(GX_CULL_NONE); | |
} | |
// Draw the actual shape... | |
GX_ClearVtxDesc(); | |
GX_SetVtxDesc(GX_VA_POS, GX_DIRECT); | |
GX_SetVtxDesc(SUPPLY_BINORMALS ? GX_VA_NBT : GX_VA_NRM, GX_DIRECT); | |
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT); | |
// Don't write depth values here, so that we can draw arrows on top of it | |
GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_FALSE); | |
GX_Begin(GX_TRIANGLESTRIP, SUPPLY_BINORMALS ? GX_VTXFMT0 : GX_VTXFMT1, vertices.size()); | |
for (auto vtx : vertices) | |
{ | |
GX_Position3f32(vtx.pos.x, vtx.pos.y, vtx.pos.z); | |
GX_Normal3f32(vtx.normal.x, vtx.normal.y, vtx.normal.z); | |
if (SUPPLY_BINORMALS) | |
{ | |
GX_Normal3f32(vtx.tangent.x, vtx.tangent.y, vtx.tangent.z); | |
GX_Normal3f32(vtx.binormal.x, vtx.binormal.y, vtx.binormal.z); | |
} | |
GX_TexCoord2f32(vtx.u, vtx.v); | |
} | |
GX_End(); | |
// And now draw lines to indicate the various parts of the calculation | |
GX_ClearVtxDesc(); | |
GX_SetVtxDesc(GX_VA_POS, GX_DIRECT); | |
GX_SetVtxDesc(GX_VA_CLR0, GX_DIRECT); | |
GX_SetNumTexGens(0); | |
GX_SetNumTevStages(1); | |
GX_SetTevOp(GX_TEVSTAGE0, GX_PASSCLR); | |
setnolight(); | |
// We want depth-testing for our lines though | |
GX_SetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); | |
f32 tex_to_pos_scale = 2.f / tex_width; | |
guVector scaledLdir; | |
guVecScale(&ldir, &scaledLdir, tex_to_pos_scale); | |
GX_Begin(GX_LINES, GX_VTXFMT2, 2 * 5 * vertices.size()); | |
for (auto vtx : vertices) | |
{ | |
guVector tangent = SUPPLY_BINORMALS ? vtx.tangent : fake_tangent; | |
guVector binormal = SUPPLY_BINORMALS ? vtx.binormal : fake_binormal; | |
guVector scaledtangent; | |
guVecScale(&tangent, &scaledtangent, tex_to_pos_scale); | |
guVector scaledbinormal; | |
guVecScale(&binormal, &scaledbinormal, tex_to_pos_scale); | |
// guVector ldirPos; | |
// guVecAdd(&vtx.pos, &scaledLdir, &ldirPos); | |
guVector tangentPos; | |
guVecSub(&vtx.pos, &scaledtangent, &tangentPos); | |
guVector binormalPos; | |
guVecSub(&vtx.pos, &scaledbinormal, &binormalPos); | |
f32 tangentFactor = guVecDotProduct(&ldir, &tangent); | |
f32 binormalFactor = guVecDotProduct(&ldir, &binormal); | |
guVector factoredtangent; | |
guVecScale(&scaledtangent, &factoredtangent, tangentFactor); | |
guVector factoredbinormal; | |
guVecScale(&scaledbinormal, &factoredbinormal, binormalFactor); | |
guVector tangentPosFactored; | |
guVecSub(&vtx.pos, &factoredtangent, &tangentPosFactored); | |
guVector binormalPosFactored; | |
guVecSub(&vtx.pos, &factoredbinormal, &binormalPosFactored); | |
guVector embossPos; | |
guVecSub(&tangentPosFactored, &factoredbinormal, &embossPos); | |
guVector ldirPos2; | |
guVecAdd(&embossPos, &scaledLdir, &ldirPos2); | |
// Indicate the light direction in red | |
// Disabled as this actually makes things more confusing | |
/* | |
WriteVec(vtx.pos); | |
GX_Color4u8(0xff, 0, 0, 0xff); | |
WriteVec(ldirPos); | |
GX_Color4u8(0xff, 0, 0, 0xff); | |
*/ | |
// Indicate the tangent green | |
WriteVec(vtx.pos); | |
GX_Color4u8(0, 0xff, 0, 0xff); | |
WriteVec(tangentPos); | |
GX_Color4u8(0, 0xff, 0, 0xff); | |
// ... and the binormal in blue | |
WriteVec(vtx.pos); | |
GX_Color4u8(0, 0, 0xff, 0xff); | |
WriteVec(binormalPos); | |
GX_Color4u8(0, 0, 0xff, 0xff); | |
// Draw lines to the embossed position | |
// Here we draw the light direction, ending AT the embossed position | |
WriteVec(ldirPos2); | |
GX_Color4u8(0xff, 0, 0, 0xff); | |
WriteVec(embossPos); | |
GX_Color4u8(0xff, 0, 0, 0xff); | |
// And now from the light direction back-calculated from the embossed position, to the vertex position | |
// This doesn't have any real meaning (with "real" tangent/binormal vectors, it'll match the normal vector) | |
// but helps with depth perception | |
/* | |
WriteVec(ldirPos2); | |
GX_Color4u8(0x80, 0, 0, 0xff); | |
WriteVec(vtx.pos); | |
GX_Color4u8(0x80, 0, 0, 0xff); | |
*/ | |
WriteVec(tangentPosFactored); | |
GX_Color4u8(0xff, 0, 0xff, 0xff); | |
WriteVec(embossPos); | |
GX_Color4u8(0xff, 0, 0xff, 0xff); | |
WriteVec(binormalPosFactored); | |
GX_Color4u8(0xff, 0xff, 0, 0xff); | |
WriteVec(embossPos); | |
GX_Color4u8(0xff, 0xff, 0, 0xff); | |
} | |
GX_End(); | |
// Draw spheres to make the light direction clearer | |
// (as well as lines to indicate the light direction) | |
for (int center_y = -1; center_y <= 1; center_y += 2) | |
{ | |
for (int center_x = -1; center_x <= 1; center_x += 2) | |
{ | |
GX_Begin(GX_LINES, GX_VTXFMT2, 2); | |
GX_Position3f32(1.5 * center_x, center_y, 0); | |
GX_Color4u8(0xff, 0, 0, 0xff); | |
f32 scale = .25f + tex_to_pos_scale; | |
GX_Position3f32(1.5 * center_x + scale * dx, center_y + scale * dy, scale * dz); | |
GX_Color4u8(0xff, 0, 0, 0xff); | |
GX_End(); | |
} | |
} | |
GX_ClearVtxDesc(); | |
GX_SetVtxDesc(GX_VA_POS, GX_DIRECT); | |
GX_SetVtxDesc(GX_VA_NRM, GX_DIRECT); | |
setlight(view, ldir, litcolors_aux[0],litcolors_aux[1],litcolors_aux[2]); | |
for (int center_y = -1; center_y <= 1; center_y += 2) | |
{ | |
for (int center_x = -1; center_x <= 1; center_x += 2) | |
{ | |
auto vertices2 = get_sphere(25, 1.5 * center_x, center_y, 0, .25); | |
GX_Begin(GX_TRIANGLESTRIP, GX_VTXFMT3, vertices2.size()); | |
for (auto vtx : vertices2) | |
{ | |
GX_Position3f32(vtx.pos.x, vtx.pos.y, vtx.pos.z); | |
GX_Normal3f32(vtx.normal.x, vtx.normal.y, vtx.normal.z); | |
} | |
GX_End(); | |
} | |
} | |
GX_DrawDone(); | |
GX_CopyDisp(frameBuffer[fb],GX_TRUE); | |
VIDEO_SetNextFramebuffer(frameBuffer[fb]); | |
if(first_frame) { | |
first_frame = 0; | |
VIDEO_SetBlack(FALSE); | |
} | |
VIDEO_Flush(); | |
VIDEO_WaitVSync(); | |
fb ^= 1; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#--------------------------------------------------------------------------------- | |
# Clear the implicit built in rules | |
#--------------------------------------------------------------------------------- | |
.SUFFIXES: | |
.SECONDARY: | |
#--------------------------------------------------------------------------------- | |
ifeq ($(strip $(DEVKITPPC)),) | |
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC") | |
endif | |
include $(DEVKITPPC)/wii_rules | |
#--------------------------------------------------------------------------------- | |
# TARGET is the name of the output | |
# BUILD is the directory where object files & intermediate files will be placed | |
# SOURCES is a list of directories containing source code | |
# INCLUDES is a list of directories containing extra header files | |
#--------------------------------------------------------------------------------- | |
TARGET := $(notdir $(CURDIR)) | |
BUILD := build | |
SOURCES := . | |
DATA := | |
TEXTURES := . | |
INCLUDES := | |
#--------------------------------------------------------------------------------- | |
# options for code generation | |
#--------------------------------------------------------------------------------- | |
CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE) | |
CXXFLAGS = $(CFLAGS) | |
LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map | |
#--------------------------------------------------------------------------------- | |
# any extra libraries we wish to link with the project | |
#--------------------------------------------------------------------------------- | |
LIBS := -lwiiuse -lbte -logc -lm | |
#--------------------------------------------------------------------------------- | |
# list of directories containing libraries, this must be the top level containing | |
# include and lib | |
#--------------------------------------------------------------------------------- | |
LIBDIRS := | |
#--------------------------------------------------------------------------------- | |
# no real need to edit anything past this point unless you need to add additional | |
# rules for different file extensions | |
#--------------------------------------------------------------------------------- | |
ifneq ($(BUILD),$(notdir $(CURDIR))) | |
#--------------------------------------------------------------------------------- | |
export OUTPUT := $(CURDIR)/$(TARGET) | |
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ | |
$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ | |
$(foreach dir,$(TEXTURES),$(CURDIR)/$(dir)) | |
export DEPSDIR := $(CURDIR)/$(BUILD) | |
#--------------------------------------------------------------------------------- | |
# automatically build a list of object files for our project | |
#--------------------------------------------------------------------------------- | |
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) | |
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) | |
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) | |
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S))) | |
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) | |
SCFFILES := $(foreach dir,$(TEXTURES),$(notdir $(wildcard $(dir)/*.scf))) | |
TPLFILES := $(SCFFILES:.scf=.tpl) | |
#--------------------------------------------------------------------------------- | |
# use CXX for linking C++ projects, CC for standard C | |
#--------------------------------------------------------------------------------- | |
ifeq ($(strip $(CPPFILES)),) | |
export LD := $(CC) | |
else | |
export LD := $(CXX) | |
endif | |
export OFILES_BIN := $(addsuffix .o,$(BINFILES)) $(addsuffix .o,$(TPLFILES)) | |
export OFILES_SOURCES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(sFILES:.s=.o) $(SFILES:.S=.o) | |
export OFILES := $(OFILES_BIN) $(OFILES_SOURCES) | |
export HFILES := $(addsuffix .h,$(subst .,_,$(BINFILES))) $(addsuffix .h,$(subst .,_,$(TPLFILES))) | |
#--------------------------------------------------------------------------------- | |
# build a list of include paths | |
#--------------------------------------------------------------------------------- | |
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ | |
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \ | |
-I$(CURDIR)/$(BUILD) \ | |
-I$(LIBOGC_INC) | |
#--------------------------------------------------------------------------------- | |
# build a list of library paths | |
#--------------------------------------------------------------------------------- | |
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ | |
-L$(LIBOGC_LIB) | |
export OUTPUT := $(CURDIR)/$(TARGET) | |
.PHONY: $(BUILD) clean | |
#--------------------------------------------------------------------------------- | |
$(BUILD): | |
@[ -d $@ ] || mkdir -p $@ | |
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile | |
#--------------------------------------------------------------------------------- | |
clean: | |
@echo clean ... | |
@rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol | |
#--------------------------------------------------------------------------------- | |
run: | |
wiiload $(OUTPUT).dol | |
#--------------------------------------------------------------------------------- | |
else | |
#--------------------------------------------------------------------------------- | |
# main targets | |
#--------------------------------------------------------------------------------- | |
$(OUTPUT).dol: $(OUTPUT).elf | |
$(OUTPUT).elf: $(OFILES) | |
$(OFILES_SOURCES) : $(HFILES) | |
#--------------------------------------------------------------------------------- | |
# This rule links in binary data with the .bin extension | |
#--------------------------------------------------------------------------------- | |
%.bin.o %_bin.h : %.bin | |
#--------------------------------------------------------------------------------- | |
@echo $(notdir $<) | |
@$(bin2o) | |
#--------------------------------------------------------------------------------- | |
%.tpl.o %_tpl.h : %.tpl | |
#--------------------------------------------------------------------------------- | |
@echo $(notdir $<) | |
@$(bin2o) | |
-include $(DEPSDIR)/*.d | |
#--------------------------------------------------------------------------------- | |
endif | |
#--------------------------------------------------------------------------------- |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment