Skip to main content
GameDev.net gamedev.net
🔒 Locked

Humus' soft shadows for spheres using GLSL

Started by sjf Jun 16, 2006 at 11:01 PM 1 replies 1.8k views
Original Post
sjf
sjf
Hi guys, I’d like to implement soft shadowing for spheres in real-time. After going through the maths of Humus’ sample (http://www.humus.ca/index.php?page=3D&&start=8) I finally understand his shadow shader and would now like to implement it – cut ‘n’ paste or by other means I don’t mind. However I’m having a very hard time trying to extract the key opengl ingredients/api-calls, and in their correct order, from his rather neat framework (2). Here are Humus’ functions of interest RE: the sphere shadows:

bool MainApp::drawFrame()
{
   renderer->changeMask(ALL);
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // added GL_COLOR_BUFFER_BIT

   ...
   // Pass 0, ambient lighting + depth
   drawRoom(0);

   // Pass 1, shadows
   vec4 spherePos[SPHERE_COUNT];
   for (unsigned int j = 0; j < SPHERE_COUNT; j++){
      spherePos[j] = vec4(spheres[j].pos, spheres[j].size * spheres[j].size);
   }

   renderer->setShader(shadow);
   renderer->setMask(ALPHA);
   renderer->apply();

   renderer->changeShaderConstant3f("lightPos", spheres[SPHERE_COUNT].pos);
   renderer->changeShaderConstantArray4f("spherePos", spherePos, SPHERE_COUNT);

   drawRoom(1);

   // Pass 2, lighting
   drawRoom(2);

   return true;
}

void MainApp::drawRoom(int pass){
   ...

   glEnableClientState(GL_VERTEX_ARRAY);
   glVertexPointer(3, GL_FLOAT, 0, vertexArray);

   if (pass != 1){
      glEnableVertexAttribArrayARB(1);
      glVertexAttribPointerARB(1, 2, GL_FLOAT, GL_FALSE, 0, texCoordArray);

      if (pass != 0){
         glEnableVertexAttribArrayARB(2);
         glEnableVertexAttribArrayARB(3);
         glEnableVertexAttribArrayARB(4);
         
         glVertexAttribPointerARB(2, 3, GL_FLOAT, GL_FALSE, 0, tangentArray);
         glVertexAttribPointerARB(3, 3, GL_FLOAT, GL_FALSE, 0, binormalArray);
         glVertexAttribPointerARB(4, 3, GL_FLOAT, GL_FALSE, 0, normalArray);
      }
   }

   if (pass == 1){
      glDrawArrays(GL_QUADS, 0, 24);
   } else {
      static int n[] = { 2, 1, 0, 0, 0, 0 };
      for (int i = 0; i < 1; i++){ // changed from “< 6"
         if (pass == 0){
            renderer->setShader(roomAmbient);
            renderer->setTexture("Base", base[n]);
            renderer->apply();
         } else {
            renderer->setShader(room);
            renderer->setTexture("Base", base[n]);
            renderer->setTexture("Bump", bump[n]);
            renderer->setBlending(DST_ALPHA, ONE);
            renderer->setMask(COLOR);
            renderer->apply();

            renderer->changeShaderConstant3f("lightPos", spheres[SPHERE_COUNT].pos);
            renderer->changeShaderConstant3f("camPos", position);
         }
         glDrawArrays(GL_QUADS, 4 * i, 4);
      }
   }

   if (pass != 1){
      if (pass != 0){
         glDisableVertexAttribArrayARB(4);
         glDisableVertexAttribArrayARB(3);
         glDisableVertexAttribArrayARB(2);
      }
      glDisableVertexAttribArrayARB(1);
   }
   glDisableClientState(GL_VERTEX_ARRAY);
}

In an effort at keeping it simple, the following is my humble attempt. And all I get to see is a RED quad for all my effort. :)


void RenderFloor(const light& point_source)
{
   static vertex quad1[4] =
   {
   //      x     y       z
      { -15.0f, 0.0f, -15.0f },
      { -15.0f, 0.0f,  15.0f },
      {  15.0f, 0.0f, -15.0f },
      {  15.0f, 0.0f,  15.0f }
   };

   static texture_normal_vertex quad2[4] =
   {
   //    tu    tv    nx    ny    nz      x     y       z
      { 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, -15.0f, 0.0f, -15.0f },
      { 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, -15.0f, 0.0f,  15.0f },
      { 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,  15.0f, 0.0f, -15.0f },
      { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,  15.0f, 0.0f,  15.0f }
   };

   glColor4f(1.0f, 0.0f, 0.0f, 1.0f); // Test color
   glInterleavedArrays(GL_V3F, 0, quad1);
   glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

   float sphere_position[MAX_SPHERES][4];
   for (int i = 0; i < MAX_SPHERES; ++i)
   {
      sphere_position[x] = spheres.position[x];
      sphere_position[y] = spheres.position[y];
      sphere_position[z] = spheres.position[z];
      sphere_position[w] = spheres.size * spheres.size;

      char str[32];
      sprintf(str, "sphere_position[%d]", i);
      shadows.Bind(str, sphere_position, 4);
   }

   shadows.Bind("light_position", point_source.position, 3); // “shadows" is my shader object.

   glDepthMask(GL_FALSE);
   glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);

   glInterleavedArrays(GL_V3F, 0, quad1);
   glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

   glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);

   shadows.Disable();

   glEnable(GL_BLEND);
   glBlendFunc(GL_DST_ALPHA, GL_ONE);

   glColor4f(0.0f, 0.0f, 1.0f, 1.0f); // Test color
   glInterleavedArrays(GL_V3F, 0, quad1);
   glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

   glDisable(GL_BLEND);
   glDepthMask(GL_TRUE);

   return;
}

Anyone have any tips, comments or suggestions relating to where I’ve screwed up or how to better debug? I normally prefer to implement my shadows in a 2 pass system instead of the above 3. I just don’t want to see Humus’ sample go to waste! Thanks anyone. PS: I’m not quite up to the stage of pulling my hair out (yet).
sjf
sjf
True, but I'm asking here. More active community et al. Get an answer faster etc...

[Edited by - sjf on June 17, 2006 9:04:14 PM]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.