Fix for bug #18228: OpenGL specular did not get the correct view

vector in perspective mode. This is default OpenGL behavior, but
by now this optimization is really insignificant. Works in both
the 3d view and game engine.
This commit is contained in:
Brecht Van Lommel 2009-02-06 19:21:24 +00:00
parent 09099111e3
commit e40803a5b3
14 changed files with 66 additions and 22 deletions

@ -82,7 +82,7 @@ int GPU_set_tpage(struct MTFace *tface);
int GPU_default_lights(void); int GPU_default_lights(void);
int GPU_scene_object_lights(struct Scene *scene, struct Object *ob, int GPU_scene_object_lights(struct Scene *scene, struct Object *ob,
int lay, float viewmat[][4]); int lay, float viewmat[][4], int ortho);
/* Text render /* Text render
* - based on moving uv coordinates */ * - based on moving uv coordinates */

@ -993,6 +993,8 @@ int GPU_default_lights(void)
U.light[2].spec[3]= 1.0; U.light[2].spec[3]= 1.0;
} }
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
glLightfv(GL_LIGHT0, GL_POSITION, U.light[0].vec); glLightfv(GL_LIGHT0, GL_POSITION, U.light[0].vec);
glLightfv(GL_LIGHT0, GL_DIFFUSE, U.light[0].col); glLightfv(GL_LIGHT0, GL_DIFFUSE, U.light[0].col);
glLightfv(GL_LIGHT0, GL_SPECULAR, U.light[0].spec); glLightfv(GL_LIGHT0, GL_SPECULAR, U.light[0].spec);
@ -1030,7 +1032,7 @@ int GPU_default_lights(void)
return count; return count;
} }
int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[][4]) int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[][4], int ortho)
{ {
Base *base; Base *base;
Lamp *la; Lamp *la;
@ -1041,6 +1043,10 @@ int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[][4
for(count=0; count<8; count++) for(count=0; count<8; count++)
glDisable(GL_LIGHT0+count); glDisable(GL_LIGHT0+count);
/* view direction for specular is not compute correct by default in
* opengl, so we set the settings ourselfs */
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (ortho)? GL_FALSE: GL_TRUE);
count= 0; count= 0;
for(base=scene->base.first; base; base=base->next) { for(base=scene->base.first; base; base=base->next) {
@ -1127,9 +1133,6 @@ void GPU_state_init(void)
GPU_default_lights(); GPU_default_lights();
/* no local viewer, looks ugly in ortho mode */
/* glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, &one); */
glDepthFunc(GL_LEQUAL); glDepthFunc(GL_LEQUAL);
/* scaling matrices */ /* scaling matrices */
glEnable(GL_NORMALIZE); glEnable(GL_NORMALIZE);

@ -82,6 +82,7 @@ void viewmoveNDOF(int mode);
void view_zoom_mouseloc(float dfac, short *mouseloc); void view_zoom_mouseloc(float dfac, short *mouseloc);
int view_mouse_depth( float mouse_worldloc[3], short mval[2], int dist); int view_mouse_depth( float mouse_worldloc[3], short mval[2], int dist);
int get_view3d_ortho(struct View3D *v3d);
int get_view3d_viewplane(int winxi, int winyi, rctf *viewplane, float *clipsta, float *clipend, float *pixsize); int get_view3d_viewplane(int winxi, int winyi, rctf *viewplane, float *clipsta, float *clipend, float *pixsize);
void setwinmatrixview3d(int winx, int winy, struct rctf *rect); void setwinmatrixview3d(int winx, int winy, struct rctf *rect);

@ -75,6 +75,7 @@
#include "BDR_drawmesh.h" #include "BDR_drawmesh.h"
#include "BSE_drawview.h" #include "BSE_drawview.h"
#include "BSE_view.h"
#include "GPU_extensions.h" #include "GPU_extensions.h"
#include "GPU_draw.h" #include "GPU_draw.h"
@ -351,9 +352,10 @@ static void draw_textured_begin(Object *ob)
solidtex= 1; solidtex= 1;
Gtexdraw.islit= -1; Gtexdraw.islit= -1;
} }
else else {
/* draw with lights in the scene otherwise */ /* draw with lights in the scene otherwise */
Gtexdraw.islit= GPU_scene_object_lights(G.scene, ob, G.vd->lay, G.vd->viewmat); Gtexdraw.islit= GPU_scene_object_lights(G.scene, ob, G.vd->lay, G.vd->viewmat, get_view3d_ortho(G.vd));
}
obcol[0]= CLAMPIS(ob->col[0]*255, 0, 255); obcol[0]= CLAMPIS(ob->col[0]*255, 0, 255);
obcol[1]= CLAMPIS(ob->col[1]*255, 0, 255); obcol[1]= CLAMPIS(ob->col[1]*255, 0, 255);

@ -1579,6 +1579,28 @@ void object_view_settings(Object *ob, float *lens, float *clipsta, float *clipen
} }
} }
int get_view3d_ortho(View3D *v3d)
{
Camera *cam;
if(v3d->persp==V3D_CAMOB) {
if(v3d->camera && v3d->camera->type==OB_CAMERA) {
cam= v3d->camera->data;
if(cam && cam->type==CAM_ORTHO)
return 1;
else
return 0;
}
else
return 0;
}
if(v3d->persp==V3D_ORTHO)
return 1;
return 0;
}
int get_view3d_viewplane(int winxi, int winyi, rctf *viewplane, float *clipsta, float *clipend, float *pixsize) int get_view3d_viewplane(int winxi, int winyi, rctf *viewplane, float *clipsta, float *clipend, float *pixsize)
{ {

@ -80,7 +80,7 @@ void KX_BlenderRenderTools::EndFrame(RAS_IRasterizer* rasty)
* has a maximum of 8 lights (simultaneous), so 20 * 8 lights are possible in * has a maximum of 8 lights (simultaneous), so 20 * 8 lights are possible in
* a scene. */ * a scene. */
void KX_BlenderRenderTools::ProcessLighting(int layer, const MT_Transform& viewmat) void KX_BlenderRenderTools::ProcessLighting(RAS_IRasterizer *rasty, int layer, const MT_Transform& viewmat)
{ {
if(m_lastlightlayer == layer) if(m_lastlightlayer == layer)
return; return;
@ -101,12 +101,12 @@ void KX_BlenderRenderTools::ProcessLighting(int layer, const MT_Transform& viewm
} }
if(enable) if(enable)
EnableOpenGLLights(); EnableOpenGLLights(rasty);
else else
DisableOpenGLLights(); DisableOpenGLLights();
} }
void KX_BlenderRenderTools::EnableOpenGLLights() void KX_BlenderRenderTools::EnableOpenGLLights(RAS_IRasterizer *rasty)
{ {
if(m_lastlighting == true) if(m_lastlighting == true)
return; return;
@ -115,7 +115,8 @@ void KX_BlenderRenderTools::EnableOpenGLLights()
glEnable(GL_COLOR_MATERIAL); glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, true); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (rasty->GetCameraOrtho())? GL_FALSE: GL_TRUE);
if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2) if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2)
glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);

@ -60,9 +60,9 @@ public:
void EndFrame(RAS_IRasterizer* rasty); void EndFrame(RAS_IRasterizer* rasty);
void BeginFrame(RAS_IRasterizer* rasty); void BeginFrame(RAS_IRasterizer* rasty);
void EnableOpenGLLights(); void EnableOpenGLLights(RAS_IRasterizer *rasty);
void DisableOpenGLLights(); void DisableOpenGLLights();
void ProcessLighting(int layer, const MT_Transform& viewmat); void ProcessLighting(RAS_IRasterizer *rasty, int layer, const MT_Transform& viewmat);
void RenderText2D(RAS_TEXT_RENDER_MODE mode, void RenderText2D(RAS_TEXT_RENDER_MODE mode,
const char* text, const char* text,

@ -85,7 +85,7 @@ void GPC_RenderTools::EndFrame(RAS_IRasterizer* rasty)
* has a maximum of 8 lights (simultaneous), so 20 * 8 lights are possible in * has a maximum of 8 lights (simultaneous), so 20 * 8 lights are possible in
* a scene. */ * a scene. */
void GPC_RenderTools::ProcessLighting(int layer, const MT_Transform& viewmat) void GPC_RenderTools::ProcessLighting(RAS_IRasterizer *rasty, int layer, const MT_Transform& viewmat)
{ {
if(m_lastlightlayer == layer) if(m_lastlightlayer == layer)
return; return;
@ -106,12 +106,12 @@ void GPC_RenderTools::ProcessLighting(int layer, const MT_Transform& viewmat)
} }
if(enable) if(enable)
EnableOpenGLLights(); EnableOpenGLLights(rasty);
else else
DisableOpenGLLights(); DisableOpenGLLights();
} }
void GPC_RenderTools::EnableOpenGLLights() void GPC_RenderTools::EnableOpenGLLights(RAS_IRasterizer *rasty)
{ {
if(m_lastlighting == true) if(m_lastlighting == true)
return; return;
@ -120,7 +120,8 @@ void GPC_RenderTools::EnableOpenGLLights()
glEnable(GL_COLOR_MATERIAL); glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, true); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (rasty->GetCameraOrtho())? GL_FALSE: GL_TRUE);
if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2) if (GLEW_EXT_separate_specular_color || GLEW_VERSION_1_2)
glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR); glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);

@ -65,9 +65,9 @@ public:
void EndFrame(RAS_IRasterizer* rasty); void EndFrame(RAS_IRasterizer* rasty);
void BeginFrame(RAS_IRasterizer* rasty); void BeginFrame(RAS_IRasterizer* rasty);
void EnableOpenGLLights(); void EnableOpenGLLights(RAS_IRasterizer *rasty);
void DisableOpenGLLights(); void DisableOpenGLLights();
void ProcessLighting(int layer, const MT_Transform& viewmat); void ProcessLighting(RAS_IRasterizer *rasty, int layer, const MT_Transform& viewmat);
/* @attention mode is ignored here */ /* @attention mode is ignored here */
void RenderText2D(RAS_TEXT_RENDER_MODE mode, void RenderText2D(RAS_TEXT_RENDER_MODE mode,

@ -255,6 +255,8 @@ public:
/** /**
*/ */
virtual const MT_Point3& GetCameraPosition()=0; virtual const MT_Point3& GetCameraPosition()=0;
virtual bool GetCameraOrtho()=0;
/** /**
*/ */
virtual void SetFog(float start, virtual void SetFog(float start,

@ -134,6 +134,7 @@ public:
virtual virtual
void void
ProcessLighting( ProcessLighting(
RAS_IRasterizer *rasty,
int layer, int layer,
const MT_Transform& trans const MT_Transform& trans
)=0; )=0;

@ -517,9 +517,9 @@ bool RAS_MaterialBucket::ActivateMaterial(const MT_Transform& cameratrans, RAS_I
return false; return false;
if (m_material->UsesLighting(rasty)) if (m_material->UsesLighting(rasty))
rendertools->ProcessLighting(RAS_IRenderTools::RAS_LIGHT_OBJECT_LAYER, cameratrans); rendertools->ProcessLighting(rasty, RAS_IRenderTools::RAS_LIGHT_OBJECT_LAYER, cameratrans);
else else
rendertools->ProcessLighting(-1, cameratrans); rendertools->ProcessLighting(rasty, -1, cameratrans);
return true; return true;
} }

@ -59,6 +59,8 @@ RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas)
m_2DCanvas(canvas), m_2DCanvas(canvas),
m_fogenabled(false), m_fogenabled(false),
m_time(0.0), m_time(0.0),
m_campos(0.0f, 0.0f, 0.0f),
m_camortho(false),
m_stereomode(RAS_STEREO_NOSTEREO), m_stereomode(RAS_STEREO_NOSTEREO),
m_curreye(RAS_STEREO_LEFTEYE), m_curreye(RAS_STEREO_LEFTEYE),
m_eyeseparation(0.0), m_eyeseparation(0.0),
@ -756,8 +758,9 @@ void RAS_OpenGLRasterizer::SetProjectionMatrix(MT_CmMatrix4x4 &mat)
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);
double* matrix = &mat(0,0); double* matrix = &mat(0,0);
glLoadMatrixd(matrix); glLoadMatrixd(matrix);
}
m_camortho= (mat(3, 3) != 0.0f);
}
void RAS_OpenGLRasterizer::SetProjectionMatrix(const MT_Matrix4x4 & mat) void RAS_OpenGLRasterizer::SetProjectionMatrix(const MT_Matrix4x4 & mat)
{ {
@ -767,6 +770,8 @@ void RAS_OpenGLRasterizer::SetProjectionMatrix(const MT_Matrix4x4 & mat)
mat.getValue(matrix); mat.getValue(matrix);
/* Internally, MT_Matrix4x4 uses doubles (MT_Scalar). */ /* Internally, MT_Matrix4x4 uses doubles (MT_Scalar). */
glLoadMatrixd(matrix); glLoadMatrixd(matrix);
m_camortho= (mat[3][3] != 0.0f);
} }
MT_Matrix4x4 RAS_OpenGLRasterizer::GetFrustumMatrix( MT_Matrix4x4 RAS_OpenGLRasterizer::GetFrustumMatrix(
@ -883,6 +888,10 @@ const MT_Point3& RAS_OpenGLRasterizer::GetCameraPosition()
return m_campos; return m_campos;
} }
bool RAS_OpenGLRasterizer::GetCameraOrtho()
{
return m_camortho;
}
void RAS_OpenGLRasterizer::SetCullFace(bool enable) void RAS_OpenGLRasterizer::SetCullFace(bool enable)
{ {

@ -80,6 +80,7 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer
MT_Matrix4x4 m_viewmatrix; MT_Matrix4x4 m_viewmatrix;
MT_Matrix4x4 m_viewinvmatrix; MT_Matrix4x4 m_viewinvmatrix;
MT_Point3 m_campos; MT_Point3 m_campos;
bool m_camortho;
StereoMode m_stereomode; StereoMode m_stereomode;
StereoEye m_curreye; StereoEye m_curreye;
@ -168,6 +169,7 @@ public:
); );
virtual const MT_Point3& GetCameraPosition(); virtual const MT_Point3& GetCameraPosition();
virtual bool GetCameraOrtho();
virtual void SetFog( virtual void SetFog(
float start, float start,