Exemplo n.º 1
0
  bool LightingVariablesHelper::MergeAsArrayItem (csShaderVariableStack& dst, 
			                          csShaderVariable* sv, 
			                          size_t index)
  {
    CS::ShaderVarStringID name = sv->GetName();
    
    if (name >= dst.GetSize()) return false;
    csShaderVariable*& dstVar = dst[name];

    if (dstVar == 0) dstVar = CreateTempSV (name);
    if ((dstVar->GetType() != csShaderVariable::UNKNOWN)
	  && (dstVar->GetType() != csShaderVariable::ARRAY)) return true;
    dstVar->SetArrayElement (index, sv);
    return true;
  }
Exemplo n.º 2
0
  void csVProcStandardProgram::SetupState (const csRenderMesh* mesh,
    csRenderMeshModes& modes,
    const csShaderVariableStack& stack)
  {
    bool skin_updated = false;// @@@ FIXME - time related detection if vertices are not already updated
    if (doVertexSkinning || doNormalSkinning || 
      doTangentSkinning || doBiTangentSkinning)
    {
      skin_updated = UpdateSkinnedVertices (modes, stack);
    }
    if (numLights > 0)
    {
      int lightsActive = 0;
      CS::ShaderVarStringID id;
      id = shaderPlugin->lsvCache.GetDefaultSVId (
        csLightShaderVarCache::varLightCount);
      csShaderVariable* sv;
      if ((stack.GetSize () > id) && ((sv = stack[id]) != 0))
        sv->GetValue (lightsActive);

      iRenderBuffer *vbuf = doVertexSkinning && skin_updated ? 
        modes.buffers->GetRenderBuffer (skinnedPositionOutputBuffer) :
        GetBuffer (positionBuffer, modes, stack);

      iRenderBuffer *nbuf = doNormalSkinning && skin_updated ? 
        modes.buffers->GetRenderBuffer (skinnedNormalOutputBuffer) :
        GetBuffer (normalBuffer, modes, stack);

      iRenderBuffer *cbuf = GetBuffer (colorBuffer, modes, stack);

      if (vbuf == 0 || nbuf == 0) return;

      csReversibleTransform camtrans;
      if ((stack.GetSize () > shaderPlugin->string_world2camera) 
        && ((sv = stack[shaderPlugin->string_world2camera]) != 0))
        sv->GetValue (camtrans);
      csVector3 eyePos (camtrans.GetT2OTranslation ());
      csVector3 eyePosObject (mesh->object2world.Other2This (eyePos));

      bool hasAlpha = cbuf && cbuf->GetComponentCount() >= 4;

      //copy output
      size_t elementCount = vbuf->GetElementCount ();
      csRef<iRenderBuffer> clbuf;
      if (doDiffuse)
      {
        clbuf = csRenderBuffer::CreateRenderBuffer (elementCount, CS_BUF_STREAM,
          CS_BUFCOMP_FLOAT, hasAlpha ? 4 : 3);
        // @@@ FIXME: should probably get rid of the multiple locking/unlocking...
        csRenderBufferLock<float> tmpColor (clbuf);
        memset (tmpColor, 0, sizeof(float) * (hasAlpha?4:3) * elementCount);
      }
      csRef<iRenderBuffer> specBuf;
      if (doSpecular)
      {
        specBuf = csRenderBuffer::CreateRenderBuffer (elementCount, 
          CS_BUF_STREAM, CS_BUFCOMP_FLOAT, 3);
        csRenderBufferLock<float> tmpColor (specBuf);
        memset (tmpColor, 0, sizeof(csColor) * elementCount);
      }
      float shininess = GetParamFloatVal (stack, shininessParam, 0.0f);

      if (lightsActive > 0)
      {
        if (lightMixMode == LIGHTMIXMODE_NONE)
        {
          //only calculate last, other have no effect
          const size_t lightNum = csMin((size_t)lightsActive, numLights)-1;

          if ((disableMask.GetSize() <= lightNum) 
            || !disableMask.IsBitSet (lightNum))
          {
            csLightProperties light (lightNum, shaderPlugin->lsvCache, stack,
              mesh->object2world);
            iVertexLightCalculator *calc = 
              shaderPlugin->GetLightCalculator (light, useAttenuation);
            calc->CalculateLighting (light, eyePosObject, shininess, elementCount, 
              vbuf, nbuf, clbuf, specBuf);
          }
        }
        else
        {
          LightMixmode useMixMode = LIGHTMIXMODE_ADD;
          for (size_t i = 0; i < (csMin((size_t)lightsActive, numLights)); i++)
          {
            if ((disableMask.GetSize() > i) && disableMask.IsBitSet (i))
            {
              useMixMode = lightMixMode;
              continue;
            }

            csLightProperties light (i, shaderPlugin->lsvCache, stack,
              mesh->object2world);
            iVertexLightCalculator *calc = 
              shaderPlugin->GetLightCalculator (light, useAttenuation);

            switch (useMixMode)
            {
            case LIGHTMIXMODE_ADD:
              {
                calc->CalculateLightingAdd (light, eyePosObject, shininess, elementCount, 
                  vbuf, nbuf, clbuf, specBuf);
                break;
              }
            case LIGHTMIXMODE_MUL:
              {
                calc->CalculateLightingMul (light, eyePosObject, shininess, elementCount,
                  vbuf, nbuf, clbuf, specBuf);
                break;
              }
            case LIGHTMIXMODE_NONE:
              break;
            }
            useMixMode = lightMixMode;
          }
        }

      }

      if (doDiffuse && cbuf)
      {
        switch (colorMixMode)
        {
        case LIGHTMIXMODE_NONE:
          if (!hasAlpha) break;
          {
            csVertexListWalker<float> cbufWalker (cbuf, 4);
            csRenderBufferLock<csVector4, iRenderBuffer*> tmpColor (clbuf);
            for (size_t i = 0; i < elementCount; i++)
            {
              const float* c = cbufWalker;
              tmpColor[i].w = c[3];
              ++cbufWalker;
            }
          }
          break;
        case LIGHTMIXMODE_ADD:
          {
            csVertexListWalker<float> cbufWalker (cbuf, 4);
            csRenderBufferLock<csVector4, iRenderBuffer*> tmpColor (clbuf);
            for (size_t i = 0; i < elementCount; i++)
            {
              csVector4& t = tmpColor[i];
              const float* c = cbufWalker;
              for (int j = 0; j < 3; j++)
                t[j] += c[j];
              if (hasAlpha) t[3] = c[3];
              ++cbufWalker;
            }
          }
          break;
        case LIGHTMIXMODE_MUL:
          {
            csVertexListWalker<float> cbufWalker (cbuf, 4);
            csRenderBufferLock<csVector4, iRenderBuffer*> tmpColor (clbuf);
            for (size_t i = 0; i < elementCount; i++)
            {
              csVector4& t = tmpColor[i];
              const float* c = cbufWalker;
              for (int j = 0; j < 3; j++)
                t[j] *= c[j];
              if (hasAlpha) t[3] = c[3];
              ++cbufWalker;
            }
          }
          break;
        default:
          CS_ASSERT (false);
        }
        if (doSpecular && specularOnDiffuse)
        {
	  csRenderBufferLock<csColor> tmpColor (clbuf);
	  csRenderBufferLock<csColor> tmpColor2 (specBuf);
	  for (size_t i = 0; i < elementCount; i++)
	  {
	    tmpColor[i] += tmpColor2[i];
	  }
        }
      }

      float finalLightFactorReal = GetParamFloatVal (stack, finalLightFactor,
	1.0f);
      if (doDiffuse)
      {
	{
	  csRenderBufferLock<csColor> tmpColor (clbuf);
	  for (size_t i = 0; i < elementCount; i++)
	  {
	    tmpColor[i] *= finalLightFactorReal;
	  }
	}
  
	modes.buffers->SetAccessor (modes.buffers->GetAccessor(),
	  modes.buffers->GetAccessorMask() & ~CS_BUFFER_COLOR_MASK);
	modes.buffers->SetRenderBuffer (CS_BUFFER_COLOR, clbuf);
      }
      if (doSpecular && !specularOnDiffuse)
      {
        csRenderBufferLock<csColor> tmpColor (specBuf);
        for (size_t i = 0; i < elementCount; i++)
        {
          tmpColor[i] *= finalLightFactorReal;
        }

        modes.buffers->SetAccessor (modes.buffers->GetAccessor(),
          modes.buffers->GetAccessorMask() & ~(1 << specularOutputBuffer));
        modes.buffers->SetRenderBuffer (specularOutputBuffer, specBuf);
      }
    }
  }