REVIEWED: shaders_spotlight example

It seems something is not working properly...
This commit is contained in:
raysan5 2020-03-24 19:49:09 +01:00
parent 05abaee0e0
commit 5e670be239
2 changed files with 134 additions and 149 deletions

View file

@ -1,27 +1,29 @@
#version 330 #version 330
// Input vertex attributes (from vertex shader)
in vec2 fragTexCoord;
in vec4 fragColor;
// Output fragment color // Output fragment color
out vec4 finalColor; out vec4 finalColor;
#define MAX_SPOTS 4 // NOTE: Add here your custom variables
#define RADIUS 256
#define INNER 200
// Inputs #define MAX_SPOTS 2
// array of spotlight positions #define RADIUS 128
uniform vec2 spots[MAX_SPOTS]; #define INNER 96
uniform float screenWidth; // width of the screen uniform vec2 spots[MAX_SPOTS]; // Spotlight positions array
uniform float screenWidth; // Width of the screen
void main() void main()
{ {
float alpha = 0.0;
float alpha; // Get the position of the current fragment (screen coordinates!)
// get the position of the current fragment (screen coordinates!)
vec2 pos = vec2(gl_FragCoord.x, gl_FragCoord.y); vec2 pos = vec2(gl_FragCoord.x, gl_FragCoord.y);
// Find out which spotlight is nearest
// find out which spotlight is nearest
float d = 65000; // some high value float d = 65000; // some high value
float di = 0; float di = 0;
@ -32,22 +34,16 @@ void main()
} }
// d now equals distance to nearest spot... // d now equals distance to nearest spot...
if (d > RADIUS) { if (d > RADIUS) alpha = 1.0;
alpha = 1.0; else
} else { {
if (d < INNER) { if (d < INNER) alpha = 0.0;
alpha = 0.0; else alpha = (d - INNER)/(RADIUS - INNER);
} else {
alpha = (d - INNER) / (RADIUS - INNER);
}
} }
// right hand side of screen is dimly lit, could make the // Right hand side of screen is dimly lit,
// threshold value user definable. // could make the threshold value user definable
if (pos.x>screenWidth/2.0 && alpha >0.9) { if ((pos.x > screenWidth/2.0) && (alpha > 0.9)) alpha = 0.9;
alpha = 0.9;
}
// could make the black out colour user definable... finalColor = vec4(0, 0, 0, alpha);
finalColor = vec4( 0, 0, 0, alpha);
} }

View file

@ -1,107 +1,91 @@
/* /*******************************************************************************************
* Copyright (c) 2019 Chris Camacho (codifies - http://bedroomcoders.co.uk/) *
* * raylib [shaders] example - Simple shader mask
* Permission is hereby granted, free of charge, to any person obtaining a copy *
* of this software and associated documentation files (the "Software"), to deal * This example has been created using raylib 2.5 (www.raylib.com)
* in the Software without restriction, including without limitation the rights * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell *
* copies of the Software, and to permit persons to whom the Software is * Example contributed by Chris Camacho (@codifies - http://bedroomcoders.co.uk/)
* furnished to do so, subject to the following conditions: * and reviewed by Ramon Santamaria (@raysan5)
* *
* The above copyright notice and this permission notice shall be included in * Copyright (c) 2019 Chris Camacho (@codifies) and Ramon Santamaria (@raysan5)
* all copies or substantial portions of the Software. *
* ********************************************************************************************
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * The shader makes alpha holes in the forground to give the apearance of a top
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * down look at a spotlight casting a pool of light...
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * The right hand side of the screen there is just enough light to see whats
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * going on without the spot light, great for a stealth type game where you
* SOFTWARE. * have to avoid the spotlights.
* *
*/ * The left hand side of the screen is in pitch dark except for where the spotlights are.
*
/* The shader makes alpha holes in the forground to give the apearance of a top * Although this example doesn't scale like the letterbox example, you could integrate
* down look at a spotlight casting a pool of light... * the two techniques, but by scaling the actual colour of the render texture rather
* * than using alpha as a mask.
* The right hand side of the screen there is just enough light to see whats *
* going on without the spot light, great for a stealth type game where you ********************************************************************************************/
* have to avoid the spotlights.
*
* The left hand side of the screen is in pitch dark except for where the spotlights
* are.
*
* Although this example doesn't scale like the letterbox example, you could integrate
* the two techniques, but by scaling the actual colour of the render texture rather
* than using alpha as a mask.
*/
#include <stddef.h>
#include <stdint.h>
#include "raylib.h" #include "raylib.h"
#include "raymath.h" #include "raymath.h"
#include <stddef.h>
#include <stdint.h>
#if defined(PLATFORM_DESKTOP) #if defined(PLATFORM_DESKTOP)
#define GLSL_VERSION 330 #define GLSL_VERSION 330
#else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB #else // PLATFORM_RPI, PLATFORM_ANDROID, PLATFORM_WEB
#define GLSL_VERSION 100 #define GLSL_VERSION 100
#endif #endif
// single digit only! #define MAXSPOT 2
#define MAXSPOT 4
#define numStars 400 #define numStars 400
#define screenWidth 1280 // Stars in the star field have a position and velocity
#define screenHeight 720 typedef struct Star {
// the stars in the star field have a position and velocity
typedef struct star {
Vector2 pos; Vector2 pos;
Vector2 vel; Vector2 vel;
} star; } Star;
void UpdateStar(Star *s);
void updateStar(star *s); void ResetStar(Star *s);
void resetStar(star *s);
int main(void) int main(void)
{ {
// Initialization // Initialization
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
star stars[numStars]; const int screenWidth = 800;
const int screenHeight = 450;
for (int n=0; n < numStars; n++) { InitWindow(screenWidth, screenHeight, "raylib - shader spotlight");
resetStar(&stars[n]);
Texture texRay = LoadTexture("resources/raysan.png");
Star stars[numStars] = { 0 };
for (int n = 0; n < numStars; n++) ResetStar(&stars[n]);
// Progress all the stars on, so they don't all start in the centre
for (int m = 0; m < screenWidth/2.0; m++)
{
for (int n = 0; n < numStars; n++) UpdateStar(&stars[n]);
} }
// progress all the stars on, so they don't all start in the centre int frameCounter = 0;
for (int m=0; m < screenWidth / 2.0; m++) {
for (int n=0; n<numStars; n++) {
updateStar(&stars[n]);
}
}
//SetConfigFlags(FLAG_FULLSCREEN_MODE);
InitWindow(screenWidth, screenHeight, "raylib - test");
Texture rayTex = LoadTexture("resources/raysan.png");
// frame counter
int frame = 0;
unsigned int spotLoc[MAXSPOT]; // shader locations unsigned int spotLoc[MAXSPOT]; // shader locations
Vector2 spotPos[MAXSPOT]; // position and velocity Vector2 spotPos[MAXSPOT]; // position and velocity
Vector2 spotVel[MAXSPOT]; Vector2 spotVel[MAXSPOT];
// use default vert shader // Use default vert shader
Shader spotShader = LoadShader(0, FormatText("resources/shaders/glsl%i/spotlight.fs", GLSL_VERSION)); Shader spotShader = LoadShader(0, FormatText("resources/shaders/glsl%i/spotlight.fs", GLSL_VERSION));
// get the locations of spots in the shader // Get the locations of spots in the shader
char spotName[32] = "spots[x]\0"; char spotName[32] = "spots[x]\0";
for (int i = 0; i<MAXSPOT; i++) { for (int i = 0; i < MAXSPOT; i++)
{
spotName[6] = '0' + i; spotName[6] = '0' + i;
spotLoc[i] = GetShaderLocation(spotShader, spotName); spotLoc[i] = GetShaderLocation(spotShader, spotName);
} }
@ -110,47 +94,47 @@ int main(void)
// a pitch black half and a dimly lit half. // a pitch black half and a dimly lit half.
{ {
unsigned int wLoc = GetShaderLocation(spotShader, "screenWidth"); unsigned int wLoc = GetShaderLocation(spotShader, "screenWidth");
float sw = screenWidth; float sw = (float)GetScreenWidth();
SetShaderValue(spotShader, wLoc, &sw, UNIFORM_FLOAT); SetShaderValue(spotShader, wLoc, &sw, UNIFORM_FLOAT);
} }
// randomise the locations and velocities of the spotlights // randomise the locations and velocities of the spotlights
for (int i=0; i<MAXSPOT; i++) { for (int i = 0; i < MAXSPOT; i++)
spotPos[i].x = GetRandomValue(128, screenWidth-128); {
spotPos[i].y = GetRandomValue(128, screenHeight-128); spotPos[i].x = GetRandomValue(64, screenWidth - 64);
spotVel[i] = (Vector2){0, 0}; spotPos[i].y = GetRandomValue(64, screenHeight - 64);
while (fabs(spotVel[i].x)+fabs(spotVel[i].y)<2) { spotVel[i] = (Vector2){ 0, 0 };
spotVel[i].x = GetRandomValue(-40,40)/10.0;
spotVel[i].y = GetRandomValue(-40,40)/10.0;
}
}
while ((fabs(spotVel[i].x) + fabs(spotVel[i].y)) < 2)
{
spotVel[i].x = GetRandomValue(-40, 40)/10.0;
spotVel[i].y = GetRandomValue(-40, 40)/10.0;
}
}
SetTargetFPS(60); // Set to run at 60 frames-per-second SetTargetFPS(60); // Set to run at 60 frames-per-second
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
// Main game loop // Main game loop
while (!WindowShouldClose()) // Detect window close button or ESC key while (!WindowShouldClose()) // Detect window close button or ESC key
{ {
// Update // Update
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
frameCounter++;
frame ++; // Move the stars, resetting them if the go offscreen
for (int n = 0; n < numStars; n++) UpdateStar(&stars[n]);
// move the stars, resetting them if the go offscreen
for (int n=0; n<numStars; n++) {
updateStar(&stars[n]);
}
// update the spots, send them to the shader
for (int i=0; i<MAXSPOT; i++) {
// Update the spots, send them to the shader
for (int i = 0; i < MAXSPOT; i++)
{
spotPos[i].x += spotVel[i].x; spotPos[i].x += spotVel[i].x;
spotPos[i].y += spotVel[i].y; spotPos[i].y += spotVel[i].y;
if (spotPos[i].x < 128) spotVel[i].x = -spotVel[i].x; if (spotPos[i].x < 64) spotVel[i].x = -spotVel[i].x;
if (spotPos[i].x > screenWidth-128) spotVel[i].x = -spotVel[i].x; if (spotPos[i].x > screenWidth - 64) spotVel[i].x = -spotVel[i].x;
if (spotPos[i].y < 128) spotVel[i].y = -spotVel[i].y; if (spotPos[i].y < 64) spotVel[i].y = -spotVel[i].y;
if (spotPos[i].y > screenHeight-128) spotVel[i].y = -spotVel[i].y; if (spotPos[i].y > screenHeight - 64) spotVel[i].y = -spotVel[i].y;
SetShaderValue(spotShader, spotLoc[i], &spotPos[i].x, UNIFORM_VEC2); SetShaderValue(spotShader, spotLoc[i], &spotPos[i].x, UNIFORM_VEC2);
} }
@ -159,22 +143,24 @@ int main(void)
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
BeginDrawing(); BeginDrawing();
ClearBackground((Color){0,32,128,255}); ClearBackground(DARKBLUE);
// stars and bobs // Draw stars and bobs
for (int n=0; n<numStars; n++) { for (int n = 0; n < numStars; n++)
// single pixel is just too small these days! {
// Single pixel is just too small these days!
DrawRectangle(stars[n].pos.x, stars[n].pos.y, 2, 2, WHITE); DrawRectangle(stars[n].pos.x, stars[n].pos.y, 2, 2, WHITE);
} }
for (int i=0; i<16; i++) { for (int i = 0; i < 16; i++)
DrawTexture(rayTex, {
(screenWidth/2.0)+cos((frame+i*8)/51.45)*(screenWidth/2.2)-32, DrawTexture(texRay,
(screenHeight/2.0)+sin((frame+i*8)/17.87)*(screenHeight/4.2), (screenWidth/2.0) + cos((frameCounter + i*8)/51.45f)*(screenWidth/2.2) - 32,
(screenHeight/2.0) + sin((frameCounter + i*8)/17.87f)*(screenHeight/4.2),
WHITE); WHITE);
} }
// spot lights // Draw spot lights
BeginShaderMode(spotShader); BeginShaderMode(spotShader);
// instead of a blank rectangle you could render here // instead of a blank rectangle you could render here
// a render texture of the full screen used to do screen // a render texture of the full screen used to do screen
@ -185,15 +171,13 @@ int main(void)
DrawFPS(10, 10); DrawFPS(10, 10);
EndDrawing(); EndDrawing();
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
} }
// De-Initialization // De-Initialization
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
UnloadTexture(texRay);
UnloadTexture(rayTex);
CloseWindow(); // Close window and OpenGL context CloseWindow(); // Close window and OpenGL context
//-------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------
@ -202,23 +186,28 @@ int main(void)
} }
void resetStar(star *s) void ResetStar(Star *s)
{ {
(*s).pos = (Vector2){screenWidth/2.0, screenHeight/2.0 }; s->pos = (Vector2){ GetScreenWidth()/2.0f, GetScreenHeight()/2.0f };
do {
(*s).vel.x = (float)GetRandomValue(-1000,1000) / 100.0; do
(*s).vel.y = (float)GetRandomValue(-1000,1000) / 100.0; {
} while (!(fabs((*s).vel.x)+fabs((*s).vel.y)>1)); s->vel.x = (float)GetRandomValue(-1000, 1000)/100.0f;
(*s).pos = Vector2Add( (*s).pos, s->vel.y = (float)GetRandomValue(-1000, 1000)/100.0f;
Vector2MultiplyV((*s).vel,(Vector2){8,8} ));
} while (!(fabs(s->vel.x) + fabs(s->vel.y) > 1));
s->pos = Vector2Add(s->pos, Vector2MultiplyV(s->vel, (Vector2){ 8, 8 }));
} }
void updateStar(star *s) void UpdateStar(Star *s)
{ {
(*s).pos = Vector2Add((*s).pos, (*s).vel); s->pos = Vector2Add(s->pos, s->vel);
if ((*s).pos.x < 0 || (*s).pos.x > screenWidth ||
(*s).pos.y < 0 || (*s).pos.y > screenHeight) { if (s->pos.x < 0 || s->pos.x > GetScreenWidth() ||
resetStar(s); s->pos.y < 0 || s->pos.y > GetScreenHeight())
{
ResetStar(s);
} }
} }