How to create basic shadows?

edited September 2015 in GLSL / Shaders

I've been trying to create shadows for some time now, but I really don't know where to start. All tutorials I find on the internet are for C++ sketches or Blender and since my knowledge in GLSL is very limited, it's very hard to convert those into processing compatible shaders. I'm looking for just a simple shadow, as basic as possible. From what I've read, the process is not that hard. Roughly: look from the light source towards every vertex, if it is visible from the light position, add it to the final fragcolor calculation. Any help would be greatly appreciated!

Thanks

My code:

import peasy.*;
PeasyCam cam;

PShape plane;
int boxSize = 10;
PShader shadow;

void setup() {
  size(1280, 720, P3D);
  frameRate(60);
  colorMode(HSB, 360, 100, 100, 100);
  smooth(8);
  background(0);

  cam = new PeasyCam(this, 100);
  plane = mesh(500, 500, 5);
  shadow = loadShader("shadowfrag.glsl", "shadowvert.glsl");
}

void draw() {
  background(0, 0, 0);
  shader(shadow);
  spotLight(0, 0, 100, 20, 20, 20, -1, -1, -1, PI/2, 2);

  noStroke();
  for(int z = 0; z < boxSize; z++) {
    for(int y = 0; y < boxSize; y++) {
      for(int x = 0; x < boxSize; x++) {
        pushMatrix();
        translate(x-boxSize/2, y-boxSize/2, z);
        box(1, 1, 1);
        popMatrix();
      }
    }
  }

  pushMatrix();
  translate(-100, -100, 0);
  scale(200);
  shape(plane);
  popMatrix();
}

PShape mesh(int xSize, int ySize, int detail) {
  ArrayList <PVector> loc = new ArrayList <PVector> ();

  for(int y = 0; y < xSize; y+=detail) {
    for(int x = 0; x < ySize; x+=detail) {
      loc.add(new PVector(x / (float)xSize, y / (float)ySize));
      loc.add(new PVector((x+detail) / (float)xSize, y / (float)ySize));
      loc.add(new PVector((x+detail) / (float)xSize, (y+detail) / (float)ySize));
      loc.add(new PVector(x / (float)xSize, (y+detail) / (float)ySize));
    }
  }

  textureMode(NORMAL);
  PShape mesh = createShape();
  mesh.beginShape(QUADS);
  mesh.fill(0,0,50);
  mesh.noStroke();
  for (PVector l : loc) mesh.vertex(l.x, l.y, l.z, l.x, l.y);
  mesh.endShape();

  return mesh;
}

I started with the shaders from the light shader tutorial, I've removed all my changes as they led nowhere. shadowvert.glsl:

#define PROCESSING_LIGHT_SHADER

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

uniform vec4 lightPosition;
uniform vec3 lightNormal;

attribute vec4 vertex;
attribute vec4 color;
attribute vec3 normal;

varying vec4 vertColor;
varying vec3 ecNormal;
varying vec3 lightDir;

void main() {
  gl_Position = transform * vertex;
  vec3 ecVertex = vec3(modelview * vertex);

  ecNormal = normalize(normalMatrix * normal);
  lightDir = normalize(lightPosition.xyz - ecVertex);
  vertColor = color;
}

shadowfrag.glsl:

#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif

varying vec4 vertColor;
varying vec3 ecNormal;
varying vec3 lightDir;

void main() {
  vec3 direction = normalize(lightDir);
  vec3 normal = normalize(ecNormal);
  float intensity = max(0.0, dot(direction, normal));
  gl_FragColor = vec4(intensity, intensity, intensity, 1) * vertColor;
}

Answers

  • Answer ✓

    I just posted a little example implementation of simple shadow mapping over in this thread.

  • Awesome! Thanks, it looks promising, I'll have a closer look a bit later...

  • The updated version looks even better, however, I am getting an error...

    Cannot compile vertex shader:ERROR: 0:1: " : #version required and missing.ERROR: 0:2: 'attribute' : syntax error: syntax error

    I'm running Processing 3 on a MacBook Pro Retina, Mid 2012, with El Capitan, any ideas?

  • edited October 2015 Answer ✓

    Glad you like it. :)

    That means your graphics card driver is kinda strict. It wants you to define the GLSL version at the top of each shader, also it should default to version 1.10.

    Just add the version requirement to the top of the shader String arrays: "#version 110",

    Edit: I added the version requirements to my shadow mapping example, let me know if that solves the problem.

  • Oh well, easy fix after all... Just put all four strings in separate .glsl files, that fixed it :-) Looks awesome, thanks for sharing!

  • So it had nothing to do with the versioning after all, just the PShader(String, String[], String[]) constructor is a little buggy on OS X. In this case I'll remove the "#version 110" in the next update.

    No problem! Glad I could help. :)

  • Hi Willemkempers, I am having the same problem. Could you explain how did you fixed it? Cheers

  • edited October 2015

    In a nutshell: make four new files, I called them vertShadowPass.glsl, fragShadowPass.glsl, vertDefaultPass.glsl and fragDefaultPass.glsl and put them in the data folder. Now copy all of the corresponding strings into those files (so vertSource goes into vertDefaultPass.glsl, fragSource goes into fragDefaultPass.glsl). You don't need the version lines and make sure to remove the quotation marks and the comma's at the end of the lines. Now rewrite the new PShader parts, so you'll end up with a function like this:

    public void initDefaultPass() {
      defaultShader = new PShader(this, "vertDefaultPass.glsl", "fragDefaultPass.glsl");
      shader(defaultShader);
      noStroke();
    }
    

    Hope that makes sense.

  • @artpen: Does willemkempers' solution work for you?

  • Sorry for the late response, I am going to try today

Sign In or Register to comment.