inline void Material::ApplyChannelControl(u8 render_alpha, bool &modulate_colors) const { if(flags->channel_control) { GX_SetChanCtrl(0, 0, 0, chan_control->color_matsrc, 0, 0, 2 ); GX_SetChanCtrl(2, 0, 0, chan_control->alpha_matsrc, 0, 0, 2 ); if(chan_control->alpha_matsrc != 1 && chan_control->color_matsrc != 1) modulate_colors = false; if(!chan_control->alpha_matsrc || !chan_control->color_matsrc) { GXColor matColor = (GXColor){0xff, 0xff, 0xff, MultiplyAlpha(0xff, render_alpha) }; if(flags->material_color) matColor = (GXColor){ mat_color->r, mat_color->g, mat_color->b, MultiplyAlpha(mat_color->a, render_alpha) }; GX_SetChanMatColor(4, matColor); if((*(u32 *)&matColor) == 0xFFFFFFFF) modulate_colors = true; } } else { GX_SetChanCtrl(4, 0, 0, 1, 0, 0, 2); } GX_SetNumChans(1); }
void SetLight(Mtx view) { guVector lpos; GXLightObj lobj; lpos.x = 0; lpos.y = 0; lpos.z = 2.0f; guVecMultiply(view,&lpos,&lpos); GX_InitLightPos(&lobj,lpos.x,lpos.y,lpos.z); GX_InitLightColor(&lobj,lightColor[0]); GX_LoadLightObj(&lobj,GX_LIGHT0); // set number of rasterized color channels GX_SetNumChans(1); GX_SetChanCtrl(GX_COLOR0A0,GX_ENABLE,GX_SRC_VTX,GX_SRC_VTX,GX_LIGHT0,GX_DF_CLAMP,GX_AF_NONE); GX_SetChanAmbColor(GX_COLOR0A0,lightColor[1]); GX_SetChanMatColor(GX_COLOR0A0,lightColor[2]); }
static void glass_postpass (void *dummy) { GXLightObj lo0; guVector ldir; #include "glass-postpass.inc" GX_SetChanAmbColor (GX_ALPHA0, (GXColor) { 0, 0, 0, 0 }); GX_SetChanMatColor (GX_ALPHA0, (GXColor) { 0, 0, 0, 255 }); GX_SetChanCtrl (GX_ALPHA0, GX_ENABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT0, GX_DF_NONE, GX_AF_SPEC); /* Light 0: use for both specular and diffuse lighting. */ guVecSub (&light0.tpos, &light0.tlookat, &ldir); guVecNormalize (&ldir); GX_InitSpecularDir (&lo0, -ldir.x, -ldir.y, -ldir.z); GX_InitLightShininess (&lo0, 128); GX_InitLightColor (&lo0, (GXColor) { 192, 192, 192, 255 }); GX_LoadLightObj (&lo0, GX_LIGHT0); }
void glEnd(void) { GX_SetCullMode(GX_CULL_FRONT); Mtx mvi; Mtx mv; // Mtx inversemodelview; // load the modelview matrix into matrix memory guMtxConcat(view,model,modelview); GX_LoadPosMtxImm(modelview, GX_PNMTX0); //for normals first calculate normal matrix (thanks shagkur) guMtxInverse(modelview,mvi); guMtxTranspose(mvi,modelview); GX_LoadNrmMtxImm(modelview,GX_PNMTX0); //experimtal leave out (hmm works good?) //use global ambient light together with current material ambient and add emissive material color GXColor constcolor; constcolor.r = (gxcurrentmaterialambientcolor.r*gxglobalambientlightcolor.r) * 0xFF; constcolor.g = (gxcurrentmaterialambientcolor.g*gxglobalambientlightcolor.g) * 0xFF; constcolor.b = (gxcurrentmaterialambientcolor.b*gxglobalambientlightcolor.b) * 0xFF; constcolor.a = (gxcurrentmaterialambientcolor.a*gxglobalambientlightcolor.a) * 0xFF; GX_SetTevColor(GX_TEVREG0, constcolor); GXColor emiscolor; emiscolor.r = gxcurrentmaterialemissivecolor.r * 0xFF; emiscolor.g = gxcurrentmaterialemissivecolor.g * 0xFF; emiscolor.b = gxcurrentmaterialemissivecolor.b * 0xFF; emiscolor.a = gxcurrentmaterialemissivecolor.a * 0xFF; GX_SetTevColor(GX_TEVREG1, emiscolor); //first check if a lightdirtyflag is set (thanks ector) so we do not have to set up light every run //also usefull on matrices etc. //now set each light GXColor gxchanambient; gxchanambient.r = gxcurrentmaterialambientcolor.r; gxchanambient.g = gxcurrentmaterialambientcolor.g; gxchanambient.b = gxcurrentmaterialambientcolor.b; gxchanambient.a = gxcurrentmaterialambientcolor.a; GXColor gxchanspecular; gxchanspecular.r = gxcurrentmaterialspecularcolor.r; gxchanspecular.g = gxcurrentmaterialspecularcolor.g; gxchanspecular.b = gxcurrentmaterialspecularcolor.b; gxchanspecular.a = gxcurrentmaterialspecularcolor.a; int lightcounter = 0; for (lightcounter =0; lightcounter < 4; lightcounter++){ if(gxlightenabled[lightcounter]){ //when light is enabled //somewhere here an error happens? //Setup mat/light ambient color gxchanambient.r = ((gxchanambient.r * gxlightambientcolor[lightcounter].r) * 0xFF); gxchanambient.g = ((gxchanambient.g * gxlightambientcolor[lightcounter].g) * 0xFF); gxchanambient.b = ((gxchanambient.b * gxlightambientcolor[lightcounter].b) * 0xFF); gxchanambient.a = ((gxchanambient.a * gxlightambientcolor[lightcounter].a) * 0xFF); GX_SetChanAmbColor(GX_COLOR0A0, gxchanambient ); //Setup diffuse material color GXColor mdc; mdc.r = (gxcurrentmaterialdiffusecolor.r * 0xFF); mdc.g = (gxcurrentmaterialdiffusecolor.g * 0xFF); mdc.b = (gxcurrentmaterialdiffusecolor.b * 0xFF); mdc.a = (gxcurrentmaterialdiffusecolor.a * 0xFF); GX_SetChanMatColor(GX_COLOR0A0, mdc ); //Setup specular material color // gxcurrentmaterialshininess * gxchanspecular.r = (gxchanspecular.r * gxlightspecularcolor[lightcounter].r) * 0xFF; gxchanspecular.g = (gxchanspecular.g * gxlightspecularcolor[lightcounter].g) * 0xFF; gxchanspecular.b = (gxchanspecular.b * gxlightspecularcolor[lightcounter].b) * 0xFF; gxchanspecular.a = (gxchanspecular.a * gxlightspecularcolor[lightcounter].a) * 0xFF; GX_SetChanMatColor(GX_COLOR1A1, gxchanspecular); // use red as test color //Setup light diffuse color GXColor ldc; ldc.r = gxlightdiffusecolor[lightcounter].r * 0xFF; ldc.g = gxlightdiffusecolor[lightcounter].g * 0xFF; ldc.b = gxlightdiffusecolor[lightcounter].b * 0xFF; ldc.a = gxlightdiffusecolor[lightcounter].a * 0xFF; GX_InitLightColor(&gxlight[lightcounter], ldc ); //move call to glend or init?; GX_InitLightColor(&gxlight[lightcounter+4], ldc ); //move call to glend or init?; //Setup light postion //check on w component when 1. light is positional // when 0. light is directional at infinite pos guVector lpos; guVector wpos; lpos.x = gxlightpos[lightcounter].x; lpos.y = gxlightpos[lightcounter].y; lpos.z = gxlightpos[lightcounter].z; if (gxlightpos[lightcounter].w == 0){ guVecNormalize(&lpos); lpos.x *= BIG_NUMBER; lpos.y *= BIG_NUMBER; lpos.z *= BIG_NUMBER; } guVecMultiply(view,&lpos,&wpos); //light position should be transformed by world-to-view matrix (thanks h0lyRS) GX_InitLightPosv(&gxlight[lightcounter], &wpos); //feed corrected coord to light pos GX_InitLightPosv(&gxlight[lightcounter+4], &wpos); //feed corrected coord to light pos //Setup light direction (when w is 1 dan dir = 0,0,0 guVector ldir; if (gxlightpos[lightcounter].w==0){ //lpos.x = gxlightpos[lightcounter].x; //lpos.y = gxlightpos[lightcounter].y; //lpos.z = gxlightpos[lightcounter].z; ldir.x = gxlightpos[lightcounter].x; ldir.y = gxlightpos[lightcounter].y; ldir.z = gxlightpos[lightcounter].z; } else { if (gxspotcutoff[lightcounter] != 180){ //if we have a spot light direction is needed ldir.x = gxspotdirection[lightcounter].x; ldir.y = gxspotdirection[lightcounter].y; ldir.z = gxspotdirection[lightcounter].z; } else { ldir.x = 0; ldir.y = 0; ldir.z = -1; } } //guVecNormalize(&ldir); //ldir.x *= BIG_NUMBER; //ldir.y *= BIG_NUMBER; //ldir.z *= BIG_NUMBER; guMtxInverse(view,mvi); guMtxTranspose(mvi,view); guVecMultiply(view,&ldir,&ldir); //and direction should be transformed by inv-transposed of world-to-view (thanks h0lyRS) GX_InitLightDir(&gxlight[lightcounter], ldir.x, ldir.y, ldir.z); //feed corrected coord to light dir GX_InitLightDir(&gxlight[lightcounter+4], ldir.x, ldir.y, ldir.z); //feed corrected coord to light dir if (gxspotcutoff[lightcounter] != 180){ //Setup specular light (only for spotlight when GL_SPOT_CUTOFF <> 180) //make this line optional? If on it disturbs diffuse light? guVector sdir; sdir.x = gxspotdirection[lightcounter].x; sdir.y = gxspotdirection[lightcounter].y; sdir.z = gxspotdirection[lightcounter].z; //guVecNormalize(&sdir); //sdir.x *= BIG_NUMBER; //sdir.y *= BIG_NUMBER; //sdir.z *= BIG_NUMBER; guVecMultiply(view,&sdir,&sdir); guVector light_dir; guVecSub(&sdir, &lpos, &light_dir); GX_TestInitSpecularDir(&gxlight[lightcounter], light_dir.x, light_dir.y, light_dir.z); //needed to enable specular light GX_TestInitSpecularDir(&gxlight[lightcounter+4], light_dir.x, light_dir.y, light_dir.z); //needed to enable specular light }; //this calls: // #define GX_InitLightShininess(lobj, shininess) (GX_InitLightAttn(lobj, 0.0F, 0.0F, 1.0F, (shininess)/2.0F, 0.0F, 1.0F-(shininess)/2.0F )) //Setup distance attinuation (opengl vs gx differences?) //GX_InitLightDistAttn(&gxlight[lightcounter], 100.0f, gxspotexponent[lightcounter], GX_DA_GENTLE); //gxspotexponent was 0.5f //ref_dist, bright, dist func //k0 = 1.0; //k1 = 0.5f*(1.0f-ref_brite)/(ref_brite*ref_dist); //k2 = 0.5f*(1.0f-ref_brite)/(ref_brite*ref_dist*ref_dist); or 0.0f; //Attenuation factor = 1 / (kc + kl*d + kq*d2) //kc = constant attenuation factor (default = 1.0) //kl = linear attenuation factor (default = 0.0) //kq = quadratic attenuation factor (default = 0.0) float distance = BIG_NUMBER; //either distance of light or falloff factor float factor = 1 / (gxconstantattanuation[lightcounter] + gxlinearattanuation[lightcounter]*distance + gxquadraticattanuation[lightcounter]*distance*distance); //float factor = 5.0; //k0 - 0; //k1 = 0.5f*(1.0f-ref_brite)/(ref_brite*ref_dist); //k2 = 0.5f*(1.0f-ref_brite)/(ref_brite*ref_dist*ref_dist); /* GX_InitLightAttn(&gxlight[lightcounter], 1.0, //filled by initlightspot 0.0, //filled by initlightspot 0.0, //filled by initlightspot gxconstantattanuation[lightcounter], gxlinearattanuation[lightcounter]*distance, gxquadraticattanuation[lightcounter]*distance*distance ) ; // k0 k1 , k2 */ //GX_InitLightAttnK(&gxlight[lightcounter], (gxcurrentmaterialshininess)/2.0F , 0.0F ,1.0F-(gxcurrentmaterialshininess)/2.0F); GX_InitLightDistAttn(&gxlight[lightcounter], factor ,1.0, GX_DA_STEEP); //gxspotexponent[lightcounter] GX_DA_GENTLE GX_InitLightDistAttn(&gxlight[lightcounter+4], factor ,1.0, GX_DA_STEEP); //gxspotexponent[lightcounter] GX_DA_GENTLE //ref_dist //ref_brite // factor / strenght //1.0 is // glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, 10.0f); ?? //Setup light type (normal/spotlight) //0-90 / 255-0 //cut_off, spot func //GX_InitLightSpot(&gxlight[lightcounter], 0.0f, GX_SP_OFF); //not this is not a spot light //GX_InitLightShininess(&gxlight[lightcounter], gxcurrentmaterialshininess); // /180? //float testspot = 90 - ((gxcurrentmaterialshininess * 90) / 128); //thanks ector 90 - (x * 90 / 255) //if (gxcurrentmaterialshininess == 0){ // testspot = 90; //} //zid 255-gxcurrentmaterialshininess/(255/90); //setup specular highlight //GX_InitLightSpot(&gxlight[lightcounter], testspot, GX_SP_COS); //not this is not a spot light (gxspotcutoff[lightcounter]) //setup normal spotlight GX_InitLightSpot(&gxlight[lightcounter], gxspotcutoff[lightcounter], GX_SP_RING1); //not this is not a spot light () GX_InitLightSpot(&gxlight[1], gxspotcutoff[lightcounter], GX_SP_RING1); //not this is not a spot light () if ( gxcurrentmaterialshininess != 0 ) { //if (gxspotcutoff[lightcounter] != 180) { GX_TestInitLightShininess(&gxlight[lightcounter+4], gxcurrentmaterialshininess); //} }; //Load the light up switch (lightcounter){ case 0: GX_LoadLightObj(&gxlight[lightcounter], GX_LIGHT0); GX_LoadLightObj(&gxlight[lightcounter+4], GX_LIGHT4); break; case 1: GX_LoadLightObj(&gxlight[lightcounter], GX_LIGHT1); GX_LoadLightObj(&gxlight[lightcounter+4], GX_LIGHT5); break; case 2: GX_LoadLightObj(&gxlight[lightcounter], GX_LIGHT2); GX_LoadLightObj(&gxlight[lightcounter+4], GX_LIGHT6); break; case 3: GX_LoadLightObj(&gxlight[lightcounter], GX_LIGHT3); GX_LoadLightObj(&gxlight[lightcounter+4], GX_LIGHT7); break; // case 4: GX_LoadLightObj(&gxlight[lightcounter], GX_LIGHT4); break; // case 5: GX_LoadLightObj(&gxlight[lightcounter], GX_LIGHT5); break; // case 6: GX_LoadLightObj(&gxlight[lightcounter], GX_LIGHT6); break; // case 7: GX_LoadLightObj(&gxlight[lightcounter], GX_LIGHT7); break; } //GX_LoadLightObj(&gxlight[lightcounter], GX_LIGHT0); //GX_LoadLightObj(&gxlight[1], GX_LIGHT1); } } //set the curtexture if tex2denabled if (tex2denabled){ GX_LoadTexObj(&gxtextures[curtexture], GX_TEXMAP0); //TODO: make GX_TEXMAP0 dynamic for multitexturing }; //now we can draw the gx way (experiment try render in reverse ivm normals pointing the wrong way) int countelements = _numelements*2; if (gxcullfaceanabled==true){ countelements = _numelements; } GX_Begin(_type, GX_VTXFMT0, countelements); //dependend on culling setting int i =0; //default //order dependend on glFrontFace(GL_CCW); //or GL_CW // for( i=0; i<_numelements; i++) //GX_TRIANGLESTRIP GL_TRIANGLE_STRIP //0 1 2 0 1 2 //1 3 2 2 1 3 //2 3 4 2 3 4 //better think of a clever swapping routine //maybe then no need to invert normal for trianglestrip anymore //also GX_TRIANLES need to be drawn in reverse? //but GX_QUAD does not //so GX = CW by default while opengl is CCW by default? //bushing say cannot i be possibel that opengl reorders vertexes //u32 reverse = 0; //int pos = 0; //int temp = 0; //GL_POLYGON: http://www.gamedev.net/reference/articles/article425.asp bool cw = true; bool ccw = true; if(gxcullfaceanabled==true){ cw = false; ccw = false; switch(gxwinding){ case GL_CW: cw = true; break; case GL_CCW: ccw = true; break; } } if (cw==true){ //CW for( i=_numelements-1; i>=0; i--) { UploadVertex(i); } } if (ccw==true){ //CCW for( i=0; i<_numelements; i++) { UploadVertex(i); } } GX_End(); //clean up just to be sure i =0; for( i=0; i<_numelements; i++) { _vertexelements[i].x = 0.0F; _vertexelements[i].y = 0.0F; _vertexelements[i].z = 0.0F; _normalelements[i].x = 0.0F; _normalelements[i].y = 0.0F; _normalelements[i].z = 0.0F; _colorelements[i].r = 0.0F; _colorelements[i].g = 0.0F; _colorelements[i].b = 0.0F; _colorelements[i].a = 0.0F; _texcoordelements[i].s = 0.0F; _texcoordelements[i].t = 0.0F; } _numelements =0; }
void gdl::Font::DrawText(const char *text, short x, short y, float scale, u_int col) { float tx; GXColor textCol; Mtx tempMatrix; if (vList == NULL) return; if (tList == NULL) return; if ((x == gdl::Centered) || (x == gdl::PCentered)) { tx = gdl::ScreenCenterX-((gdl::Font::CalcStrLen(text)*scale)/2)+(scale/2); } else { tx = x; } textCol.r = RED(col); textCol.g = GREEN(col); textCol.b = BLUE(col); textCol.a = ALPHA(col); GX_LoadTexObj(gdl::Font::charSheet.TexObj(), GX_TEXMAP0); GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE); GX_ClearVtxDesc(); GX_SetVtxDesc(GX_VA_POS, GX_INDEX16); GX_SetVtxDesc(GX_VA_TEX0, GX_INDEX16); GX_SetArray(GX_VA_POS, gdl::Font::vList, 2*sizeof(s16)); GX_SetArray(GX_VA_TEX0, gdl::Font::tList, 2*sizeof(f32)); GX_SetChanCtrl(GX_COLOR0A0, GX_DISABLE, GX_SRC_VTX, GX_SRC_REG, 0, GX_DF_NONE, GX_AF_NONE); GX_SetChanMatColor(GX_COLOR0A0, textCol); guMtxCopy(gdl::wii::ModelMtx, tempMatrix); guMtxApplyTrans(tempMatrix, tempMatrix, tx, y, 0); guMtxApplyScale(tempMatrix, tempMatrix, scale, scale, 0); GX_LoadPosMtxImm(tempMatrix, GX_PNMTX0); for(int i=0; text[i]!=0x00; i++) { int tc=4*((u_char)text[i]); GX_Begin(GX_QUADS, GX_VTXFMT0, 4); GX_Position1x16(tc); GX_TexCoord1x16(tc); GX_Position1x16(tc+1); GX_TexCoord1x16(tc+1); GX_Position1x16(tc+2); GX_TexCoord1x16(tc+2); GX_Position1x16(tc+3); GX_TexCoord1x16(tc+3); GX_End(); guMtxApplyTrans(tempMatrix, tempMatrix, gdl::Font::charWidth[(u_char)text[i]], 0, 0); GX_LoadPosMtxImm(tempMatrix, GX_PNMTX0); } GX_LoadPosMtxImm(gdl::wii::ModelMtx, GX_PNMTX0); GX_SetChanCtrl(GX_COLOR0A0, GX_DISABLE, GX_SRC_VTX, GX_SRC_VTX, 0, GX_DF_NONE, GX_AF_NONE); }
void gdl::FFont::DrawText(const char *text, short x, short y, float scale, u32 col) { // Draws text using the current font set by gdl_SetCurrentFont() float tx; int c,tc; Mtx TempMatrix; GXColor TempCol; if (vList == NULL) return; if ((x == gdl::Centered) || (x == gdl::PCentered)) { tx = gdl::ScreenCenterX - ((((cw+1)*strlen(text))*scale)/2)+(scale/2); } else { tx = x; } TempCol.r = RED(col); TempCol.g = GREEN(col); TempCol.b = BLUE(col); TempCol.a = ALPHA(col); GX_LoadTexObj(charTexObj, GX_TEXMAP0); GX_SetTevOp(GX_TEVSTAGE0, GX_MODULATE); GX_ClearVtxDesc(); GX_SetVtxDesc(GX_VA_POS, GX_INDEX8); GX_SetVtxDesc(GX_VA_TEX0, GX_INDEX16); GX_SetArray(GX_VA_POS, vList, 2*sizeof(s16)); GX_SetArray(GX_VA_TEX0, tList, 2*sizeof(f32)); guMtxCopy(gdl::wii::ModelMtx, TempMatrix); guMtxApplyTrans(TempMatrix, TempMatrix, tx, y, 0); guMtxApplyScale(TempMatrix, TempMatrix, scale, scale, 0); GX_LoadPosMtxImm(TempMatrix, GX_PNMTX0); GX_SetChanCtrl(GX_COLOR0A0, GX_DISABLE, GX_SRC_VTX, GX_SRC_REG, 0, GX_DF_NONE, GX_AF_NONE); GX_SetChanMatColor(GX_COLOR0A0, TempCol); for(c=0; text[c] != 0x00; c++) { tc = 4*((u_char*)text)[c]; GX_Begin(GX_QUADS, GX_VTXFMT0, 4); GX_Position1x8(0); GX_TexCoord1x16(tc); GX_Position1x8(1); GX_TexCoord1x16(tc+1); GX_Position1x8(2); GX_TexCoord1x16(tc+2); GX_Position1x8(3); GX_TexCoord1x16(tc+3); GX_End(); guMtxApplyTrans(TempMatrix, TempMatrix, cw+1, 0, 0); GX_LoadPosMtxImm(TempMatrix, GX_PNMTX0); } GX_LoadPosMtxImm(gdl::wii::ModelMtx, GX_PNMTX0); GX_SetChanCtrl(GX_COLOR0A0, GX_DISABLE, GX_SRC_VTX, GX_SRC_VTX, 0, GX_DF_NONE, GX_AF_NONE); }