Изменение направления прожектора в обработке - PullRequest
3 голосов
/ 11 февраля 2020

Я пытаюсь реализовать 2 прожектора в верхней части сцены, используя Processing, который со временем меняет свое направление. Я попытался использовать метод spotlight(r,g,b,x,y,z,nx,ny,nz,angle,concentration) по умолчанию для создания прожекторов и попытался изменить переменные nx, ny и nz, чтобы изменить направление света. Тем не менее, метод, кажется, не принимает 3 переменных. Это glsl, который я использую.

precision mediump float;

varying vec3 normalInterp;
varying vec3 vertPos;



uniform int lightCount;
uniform vec4 lightPosition[8];
uniform vec3 lightNormal[8];


//ambient
const vec3 ambientColor = vec3(0.1, 0, 0);
//diffuse
const vec3 diffuseColor = vec3(0.5, 0.0, 0.0);
//specular
const vec3 specColor = vec3(1.0, 1.0, 1.0);
//specular reflection parameter
const float n = 30.0;
//Depth cueing
//not implemented

void main() {

  float lightR = 0.0;
  float lightG = 0.0;
  float lightB = 0.0;

  for (int i = 0; i < lightCount; i++)
  {
   vec3 normal = normalize(normalInterp);
   vec3 lightDir = normalize(lightPosition[i] - vertPos);

   //diffuse
   float diffuse = max(dot(lightDir,normal), 0.0);

   //specular
   float specular = 0.0;
   if(diffuse > 0.0) {
      vec3 viewDir = normalize(-vertPos);
      vec3 reflectDir = reflect(-lightDir, normal);
      float specAngle = max(dot(reflectDir, viewDir), 0.0);
      specular = pow(specAngle, n);
  }

  //Note: can add in depth cueing here
  vec3 colorLinear = ambientColor +
                     diffuse * diffuseColor +
                     specular * specColor;

  lightR += colorLinear.x;
  lightG += colorLinear.y;
  lightB += colorLinear.z;

  }

  gl_FragColor = vec4(lightR,lightG,lightB, 1.0);
}

1 Ответ

1 голос
/ 11 февраля 2020

В шейдерной программе есть простая проблема. Сначала опечатка. Это должно быть lightPosition, а не lightPostion. Но это не единственная проблема.

Тип lightPosition[i] - vec4, а опечатка vertPos - vec3. Это вызывает и ошибку, когда vertPos вычитается из lightPosition[i].

Либо вы должны построить vec3 из lightPosition[i]:

vec3 lightDir = normalize(lightPostion[i] - vertPos);

vec3 lightDir = normalize(vec3(lightPosition[i]) - vertPos);

Или Вы должны получить x, y и z компонент вида lightPosition[i] (см. Swizzling ):

vec3 lightDir = normalize(lightPosition[i].xyz - vertPos);

Оба решения приводят к одному и тому же результату.


Конечно, Положение света должно быть установлено относительно объекта. Обратите внимание, что при вызове spotLight() положение и направление источника света преобразуется с помощью матрицы вида текущей модели.

См. Пример:

Вершинный шейдер

uniform mat4 modelview;
uniform mat4 transform;
uniform mat3 normalMatrix;

attribute vec4 position;
attribute vec4 color;
attribute vec3 normal;

varying vec3 normalInterp;
varying vec3 vertPos;

varying vec4 vertColor;

void main() {
    gl_Position = transform * position;
    vertPos = vec3(modelview * position);
    normalInterp = normalize(normalMatrix * normal);
}

Фрагментный шейдер

precision mediump float;

varying vec3 normalInterp;
varying vec3 vertPos;

uniform int lightCount;
uniform vec4 lightPosition[8];
uniform vec3 lightNormal[8];
uniform vec3 lightDiffuse[8];
uniform vec3 lightSpecular[8];
uniform vec2 lightSpot[8];

const vec3 ambientColor = vec3(0.2);
const vec3 diffuseColor = vec3(1.0);
const vec3 specColor = vec3(1.0);
const float n = 30.0;

void main() {

    vec3 lightColor = vec3(0.0, 0.0, 0.0);

    for (int i = 0; i < lightCount; i++)
    {
        // ambient
        lightColor += lightDiffuse[i] * ambientColor;

        vec3 normal = normalize(normalInterp);
        vec3 lightDir = normalize(lightPosition[i].xyz - vertPos);

        float spot = dot(-lightNormal[i], lightDir);
        if (spot < lightSpot[i].x)
            continue;

        //diffuse
        float diffuse = max(dot(lightDir,normal), 0.0);
        lightColor += diffuse * lightDiffuse[i] * diffuseColor;

        //specular
        if(diffuse > 0.0) {
            vec3 viewDir = normalize(-vertPos);
            vec3 reflectDir = reflect(-lightDir, normal);
            float specAngle = max(dot(reflectDir, viewDir), 0.0);
            float specular = pow(specAngle, n);
            lightColor += specular * lightSpecular[i] * specColor;
        }
    }

    gl_FragColor = vec4(lightColor.rgb, 1.0);
}

Код

PShader lightShader;

void setup() {
    size(800, 600, P3D);
    lightShader = loadShader("fragment.glsl","vertex.glsl");
}

float ry = 0.0;
void draw() {
    background(0);

    shader(lightShader);

    translate(width/2.0, height/2.0);

    spotLight(255, 0, 0, 0, 500, 500, 0, -1, -1, PI/25, 2);
    spotLight(0, 0, 255, 500, 0, 500, -1, 0, -1, PI/25, 2);

    rotateY(ry);
    rotateX(-0.5);
    ry += 0.02;

    noStroke();
    box(200);
}
...