# GLSL: Shader input not present

I am trying to implement Sean O’Neil’s Atmosphere from space glsl shader, but my shading n00bness ran into a confusing problem, so I add one line of code at a time. When I add a for loop I get AssertionError: Shader input nSamples is not present.
despite having it set in code. Remove the for loop and nSamples suddenly exists.

Vertex shader a2.glsl:

``````//GLSL
//
// Atmospheric scattering vertex shader
//
// Author: Sean O'Neil
//
// Copyright (c) 2004 Sean O'Neil
//

uniform vec3 v3CameraPos;       // The camera's current position
uniform vec3 v3LightPos;        // The direction vector to the light source
uniform float fOuterRadius;     // The outer (atmosphere) radius
uniform float fOuterRadius2;    // fOuterRadius^2
uniform float fInnerRadius;

uniform vec3 v3InvWavelength;   // 1 / pow(wavelength, 4) for the red, green, and blue channels

uniform float fScale;           // 1 / (fOuterRadius - fInnerRadius)
uniform float fScaleDepth;      // The scale depth (i.e. the altitude at which the atmosphere's average density is found)
uniform float fScaleOverScaleDepth; // fScale / fScaleDepth

uniform float fKr4PI;           // Kr * 4 * PI
uniform float fKm4PI;           // Km * 4 * PI

uniform float fSamples;
uniform float nSamples;

varying vec3 v3Direction;

float scale(float fCos)
{
float x = 1.0 - fCos;
return fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25))));
}

void main(void)
{
// Get the ray from the camera to the vertex and its length (which is the far point of the ray passing through the atmosphere)
vec3 v3Pos = gl_Vertex.xyz;
vec3 v3Ray = v3Pos - v3CameraPos;
float fFar = length(v3Ray);
v3Ray /= fFar;

// Calculate the closest intersection of the ray with the outer atmosphere (which is the near point of the ray passing through the atmosphere)
float B = 2.0 * dot(v3CameraPos, v3Ray);
//float C = fCameraHeight2 - fOuterRadius2;
float C = 0.0 - fOuterRadius2;
float fDet = max(0.0, B*B - 4.0 * C);
float fNear = 0.5 * (-B - sqrt(fDet));

// Calculate the ray's starting position, then calculate its scattering offset
vec3 v3Start = v3CameraPos + v3Ray * fNear;
fFar -= fNear;
float fStartAngle = dot(v3Ray, v3Start) / fOuterRadius;
float fStartDepth = exp(-1.0 / fScaleDepth);
float fStartOffset = fStartDepth*scale(fStartAngle);

// Initialize the scattering loop variables
//gl_FrontColor = vec4(0.0, 0.0, 0.0, 0.0);
float fSampleLength = fFar / fSamples;
float fScaledLength = fSampleLength * fScale;
vec3 v3SampleRay = v3Ray * fSampleLength;
vec3 v3SamplePoint = v3Start + v3SampleRay * 0.5;

// Now loop through the sample rays
vec3 v3FrontColor = vec3(0.0, 0.0, 0.0);
// Next line causes breakage
for(int i=0; i<nSamples; i++)
{
float fHeight = length(v3SamplePoint);
float fDepth = exp(fScaleOverScaleDepth * (fInnerRadius - fHeight));
float fLightAngle = dot(v3LightPos, v3SamplePoint) / fHeight;
float fCameraAngle = dot(v3Ray, v3SamplePoint) / fHeight;
float fScatter = (fStartOffset + fDepth*(scale(fLightAngle) - scale(fCameraAngle)));
vec3 v3Attenuate = exp(-fScatter * (v3InvWavelength * fKr4PI + fKm4PI));
v3FrontColor += v3Attenuate * (fDepth * fScaledLength);
v3SamplePoint += v3SampleRay;
}

gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

v3Direction = 0.0-v3Pos;
}
``````

Temporary Fragment shader a3.glsl

``````//GLSL
//
// Atmospheric scattering fragment shader
//
// Author: Sean O'Neil
//
// Copyright (c) 2004 Sean O'Neil
//

varying vec3 v3Direction;

void main (void)
{

}

``````

And code

``````self.atmosphere = loader.loadModel("planet_sphere")
self.atmosphere.setColor(0.5,0.5,1,0.5)
outerRadius = self.radius + bodyDB['atmosphere']['thickness']
self.atmosphere.setShaderInput("fOuterRadius", outerRadius)
self.atmosphere.setShaderInput('fOuterRadius2', outerRadius**2)
self.atmosphere.setShaderInput("v3CameraPos", 0,0, 0)
self.atmosphere.setShaderInput("v3LightPos", -149598261, 20000, 0)
Km = 0.0025 # Mie scattering constant
ESun = 15.0 # Sun brightness constant
Kr = 0.0025 #Rayleigh scattering constant
self.atmosphere.setShaderInput("fKm4PI", Km*4*3.14)
self.atmosphere.setShaderInput("fKr4PI", Kr*4*3.14)
self.atmosphere.setShaderInput("fKmESun", Km*ESun)
self.atmosphere.setShaderInput("fKrESun", Kr*ESun)
self.atmosphere.setShaderInput("nSamples", 2.0)
self.atmosphere.setShaderInput("fSamples", 2.0)
self.atmosphere.setShaderInput('fScale' , 1.0/outerRadius-self.radius)     # 1 / (fOuterRadius - fInnerRadius)
self.atmosphere.setShaderInput('fScaleDepth' , 0.25)
self.atmosphere.setShaderInput('fScaleOverScaleDepth' , (1.0/outerRadius-self.radius)/0.25)
self.atmosphere.setShaderInput('g', -0.95) #;		// The Mie phase asymmetry factor
self.atmosphere.setShaderInput('g2', -0.95**2)
m_fWavelength4 = [0,0,0]
m_fWavelength4[0] = 0.650**4 # 650 nm for red
m_fWavelength4[1] = 0.570**4 # 570 nm for green
m_fWavelength4[2] = 0.475**4 # 475 nm for blue
self.atmosphere.setShaderInput("v3InvWavelength", 1/m_fWavelength4[0], 1/m_fWavelength4[1], 1/m_fWavelength4[2])
self.atmosphere.setShaderInput('fInnerRadius', float(self.radius))
self.atmosphere.setShaderInput('fInnerRadius2', float(self.radius)**2)
self.atmosphere.setShaderInput('fInnerRadius', self.radius**2)
#atmoShader = Shader.load(Shader.SLGLSL, "AtmoVert.glsl", "AtmoFrag.glsl")
atmoShader = Shader.load(Shader.SLGLSL, "a2.glsl", "a3.glsl")
#atmoShader = Shader.load(Shader.SLGLSL, "AtmoFrag.glsl", "AtmoVert.glsl")
#atmoShader = Shader.load("atmosphere2.cg")
self.atmosphere.setShader(atmoShader)``````

see this thread
discourse.panda3d.org/viewtopic.php?t=9264

Might be the same problem and perhaps it’s already fixed in nightly build.