2025-01-26 18:33:45 +01:00

263 lines
6.7 KiB
C

/*
Raydium - CQFD Corp.
http://raydium.org/
License: GPL - GNU General Public License, see "gpl.txt" file.
*/
#ifndef DONT_INCLUDE_HEADERS
#include "index.h"
#else
#include "headers/shadow.h"
#endif
#include "shadow.h"
void raydium_shadow_init(void)
{
raydium_shadow_tag=0;
raydium_shadow_ground_mesh=-1;
raydium_shadow_rendering=0;
raydium_log("shadow: OK");
}
void raydium_shadow_ground_change(int object)
{
//modelsize, center factors
GLfloat min[3],max[3];
GLfloat tx,ty,tz;
GLfloat x,y,z;
if(!raydium_object_isvalid(object))
{
raydium_log("shadow: ERROR: ground id or name is invalid");
return;
}
raydium_shadow_ground_mesh=object;
raydium_object_find_center_factors(object,&x,&y,&z);
raydium_shadow_ground_center_factor_x=0.5-x;
raydium_shadow_ground_center_factor_y=0.5-y;
raydium_object_find_minmax(object,min,max);
tx=max[0]-min[0];
ty=max[1]-min[1];
tz=max[2]-min[2];
raydium_shadow_ground_modelsize=raydium_trigo_max(tx,raydium_trigo_max(ty,tz));
raydium_shadow_ground_modelsize/=2;
raydium_log("shadow: ground (%i) modelsize is %.2f, center factors : %.2f/%.2f",
raydium_shadow_ground_mesh,
raydium_shadow_ground_modelsize,
raydium_shadow_ground_center_factor_x,
raydium_shadow_ground_center_factor_y);
}
void raydium_shadow_enable(void)
{
float S[]={1.0, 0.0, 0.0, 0.0};
float T[]={0.0, 1.0, 0.0, 0.0};
float R[]={0.0, 0.0, 1.0, 0.0};
float Q[]={0.0, 0.0, 0.0, 1.0};
int tmp;
if(raydium_shadow_tag)
return;
raydium_shadow_tag=1;
// There was a previous call
if(raydium_texture_exists(RAYDIUM_SHADOW_TEXTURE)!=-1)
return;
tmp=1;
while(tmp<=raydium_window_tx &&
tmp<=raydium_window_ty &&
tmp<=raydium_texture_size_max)
{
tmp*=2;
}
raydium_shadow_map_size=tmp/2;
raydium_log("shadow: shadow map size detected to %ix%i",raydium_shadow_map_size,raydium_shadow_map_size);
glPushMatrix();
glLoadIdentity();
glTexGenfv(GL_S,GL_EYE_PLANE,S);
glTexGenfv(GL_T,GL_EYE_PLANE,T);
glTexGenfv(GL_R,GL_EYE_PLANE,R);
glTexGenfv(GL_Q,GL_EYE_PLANE,Q);
glPopMatrix();
raydium_shadow_texture=raydium_texture_load_internal("",RAYDIUM_SHADOW_TEXTURE,1,raydium_shadow_map_size,raydium_shadow_map_size,4,-1);
//raydium_shadow_texture=raydium_texture_load("shadowmap1.tga"); // debug
}
void raydium_shadow_disable(void)
{
raydium_shadow_tag=0;
}
signed char raydium_shadow_isenabled(void)
{
return raydium_shadow_tag;
}
void raydium_shadow_light_main(GLuint l)
{
raydium_shadow_light=l;
}
void raydium_shadow_object_draw(GLuint o)
{
#ifndef DEBUG_RENDER_DISABLE_DISPLAYLISTS
static GLuint dl[RAYDIUM_MAX_OBJECTS];
static char dl_state[RAYDIUM_MAX_OBJECTS];
static int first=0;
int i;
if(first)
for(i=0;i<RAYDIUM_MAX_OBJECTS;i++)
dl_state[i]=-1;
if(raydium_render_displaylists_tag && raydium_object_anims[o]==0)
{
if(!dl_state[o])
{
// build DL
dl_state[o]=1;
dl[o]=glGenLists(1);
raydium_log("Object: creating **shadow** display list for object %s",raydium_object_name[o]);
glNewList(dl[o],GL_COMPILE);
raydium_rendering_from_to_simple(raydium_object_start[o],raydium_object_end[o]);
glEndList();
}
glCallList(dl[o]);
}
else
raydium_rendering_from_to_simple(raydium_object_start[o],raydium_object_end[o]);
#else
raydium_rendering_from_to_simple(raydium_object_start[o],raydium_object_end[o]);
#endif
}
void raydium_shadow_map_generate(void)
{
// test shadow support and ground
if(!raydium_shadow_tag || raydium_shadow_ground_mesh<0)
return;
glViewport(0,0,raydium_shadow_map_size,raydium_shadow_map_size);
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glTranslatef((raydium_shadow_ground_center_factor_x-0.5)*2,(raydium_shadow_ground_center_factor_y-0.5)*2,0);
glOrtho(-raydium_shadow_ground_modelsize,raydium_shadow_ground_modelsize,
-raydium_shadow_ground_modelsize,raydium_shadow_ground_modelsize,
-1000,1000); // should probably use far clipping
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(raydium_light_position[raydium_shadow_light][0]*0,
raydium_light_position[raydium_shadow_light][1]*0,
raydium_light_position[raydium_shadow_light][2], 0,0,0, 0,1,0);
glDisable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glColor4f(RAYDIUM_SHADOW_OPACITY,RAYDIUM_SHADOW_OPACITY,RAYDIUM_SHADOW_OPACITY,1);
raydium_shadow_rendering=1;
glPushMatrix();
#ifdef ODE_SUPPORT
//raydium_ode_draw_all(RAYDIUM_ODE_DRAW_SHADOWERS); // static compile time linking disallow using this constant
raydium_ode_draw_all(4);
#endif
glPopMatrix();
raydium_shadow_rendering=0;
raydium_clear_color_update();
if(raydium_light_enabled_tag)
glEnable(GL_LIGHTING);
#ifdef DEBUG_SHADOW_MAP_VIEW
glutSwapBuffers();
#endif
glBindTexture(GL_TEXTURE_2D,raydium_shadow_texture);
glCopyTexSubImage2D(GL_TEXTURE_2D,0,0,0,0,0,raydium_shadow_map_size,raydium_shadow_map_size);
glColor4f(1,1,1,1);
glViewport(0,0,raydium_window_tx,raydium_window_ty);
glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
// apply shadow map to ground
void raydium_shadow_map_render(void)
{
float mview[16],imview[16];
// test shadow support and ground
if(!raydium_shadow_tag || raydium_shadow_ground_mesh<0)
return;
raydium_camera_replace();
glEnable(GL_TEXTURE_GEN_S);
glEnable(GL_TEXTURE_GEN_T);
glEnable(GL_TEXTURE_GEN_R);
glEnable(GL_TEXTURE_GEN_Q);
glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
glTexGeni(GL_R,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
glTexGeni(GL_Q,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
glGetFloatv(GL_MODELVIEW_MATRIX,mview);
_raydium_trigo_MatrixInverse(mview,imview);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glTranslatef(raydium_shadow_ground_center_factor_x,raydium_shadow_ground_center_factor_y,0);
glScalef(0.5,0.5,1.0);
glColor4f(1,1,1,1);
glOrtho(-raydium_shadow_ground_modelsize,raydium_shadow_ground_modelsize,
-raydium_shadow_ground_modelsize,raydium_shadow_ground_modelsize,
-1,1);
gluLookAt(raydium_light_position[raydium_shadow_light][0]*0,
raydium_light_position[raydium_shadow_light][1]*0,
raydium_light_position[raydium_shadow_light][2], 0,0,0, 0,1,0);
glMultMatrixf(imview);
glDisable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_ZERO,GL_ONE_MINUS_SRC_COLOR);
glBindTexture(GL_TEXTURE_2D,raydium_shadow_texture);
//glBindTexture(GL_TEXTURE_2D,raydium_texture_find_by_name("shadowmap1.tga")); // debug
raydium_shadow_object_draw(raydium_shadow_ground_mesh);
glDisable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glMatrixMode(GL_TEXTURE);
glLoadIdentity(); // reset GL_TEXTURE matrix
glMatrixMode(GL_MODELVIEW);
glDisable(GL_TEXTURE_GEN_S);
glDisable(GL_TEXTURE_GEN_T);
glDisable(GL_TEXTURE_GEN_R);
glDisable(GL_TEXTURE_GEN_Q);
}