Texture scale in GLSL using pixi-js - glsl

I want to scale the textures so they can be centered and scaled so they cover the space without distorting the image. I tried some things but I don't seem to get it to work with the uniforms provided by pixi-js. I'm still a noob at GLSL /pixi.
Here is a codepen link with the problem: https://codepen.io/sergiulucutar/pen/JjKXKKw?editors=0010
const app = new PIXI.Application({
width: window.innerWidth,
height: window.innerHeight,
antialias: true,
resizeTo: window,
transparent: true
});
document.body.appendChild(app.view);
//Image
const vertexShader = `
precision mediump float;
attribute vec2 aVertexPosition;
attribute vec2 aSize;
uniform mat3 translationMatrix;
uniform mat3 projectionMatrix;
varying vec2 vUvs;
uniform vec2 uSize;
void main() {
vUvs = vec2(aVertexPosition.x / uSize.x, aVertexPosition.y / uSize.y);
gl_Position = vec4((projectionMatrix * translationMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);
}
`;
const fragmentShader = `
precision mediump float;
varying vec2 vUvs;
uniform sampler2D uTexture;
void main() {
gl_FragColor = texture2D(uTexture, vUvs);
}
`;
const width = 1400;
const height = 300;
const uniforms = {
uTexture: PIXI.Texture.from(imageUrl),
uSize: [width, height],
uTime: 0
};
const shader = PIXI.Shader.from(vertexShader, fragmentShader, uniforms);
const mesh = new PIXI.Mesh(new PIXI.PlaneGeometry(width, height, 32, 32), shader);
mesh.position.y = 100;
app.stage.addChild(mesh);

Related

Problems with water shader (don't want to refract object above water)

I have created a water shader which has a problem with refraction. It's not only refracting object under water (which it should) - it's also refracting object which is not in water.
Here is the full source of the fragment shader.
varying vec2 v_UV1;
uniform sampler2D u_Scene;
uniform sampler2D u_Depth;
uniform sampler2D u_WaterDUDV;
uniform vec2 u_ViewSize;
uniform float u_Time;
uniform vec3 u_Color;
uniform float u_Transparency;
void main() {
float transparency = u_Transparency;
vec4 waterColor = vec4(u_Color, 1.0);
vec2 uv = v_UV1 + vec2(0.3, 0.1) * u_Time;
vec2 dudv = texture2D(u_WaterDUDV, uv).rg * 2.0 - 1.0;
vec2 finalSceneUV = gl_FragCoord.xy / u_ViewSize;
vec2 sceneUV = gl_FragCoord.xy / u_ViewSize;
vec2 sceneOffsetUV = sceneUV + dudv * 0.007;
float sceneDepth = texture2D(u_Depth, sceneUV).r;
float sceneOffsetDepth = texture2D(u_Depth, sceneOffsetUV).r;
if (sceneDepth < gl_FragCoord.z) {
transparency = 0.0;
} else {
// The cube is viewed though water.
finalSceneUV = sceneOffsetUV;
}
vec4 sceneColor = texture2D(u_Scene, finalSceneUV);
vec4 finalColor = mix(sceneColor, waterColor, transparency);
gl_FragColor = finalColor;
}
Any ideas how this could be fixed?

Porting ShaderToy Chromakey example to P5.js

I’m try to porting the shadertoy chromakey example to p5 with webcam as video source. After many time reading documentations of shaders, my code seems not working. I need some help.
I followed this guide to port the code for the p5
Fragment shader code:
#ifdef GL_ES
precision mediump float;
#endif
uniform sampler2D tex0;
uniform sampler2D tex1;
mat4 RGBtoYUV = mat4(0.257, 0.439, -0.148, 0.0,
0.504, -0.368, -0.291, 0.0,
0.098, -0.071, 0.439, 0.0,
0.0625, 0.500, 0.500, 1.0 );
vec4 chromaKey = vec4(0.05, 0.63, 0.14, 1);
vec2 maskRange = vec2(0.005, 0.26);
float colorclose(vec3 yuv, vec3 keyYuv, vec2 tol)
{
float tmp = sqrt(pow(keyYuv.g - yuv.g, 2.0) + pow(keyYuv.b - yuv.b, 2.0));
if (tmp < tol.x)
return 0.0;
else if (tmp < tol.y)
return (tmp - tol.x)/(tol.y - tol.x);
else
return 1.0;
}
void main()
{
vec2 fragPos = gl_FragCoord.xy / iResolution.xy;
vec4 texColor0 = texture(text0, fragPos);
vec4 texColor1 = texture(text1, fragPos);
vec4 keyYUV = RGBtoYUV * chromaKey;
vec4 yuv = RGBtoYUV * texColor0;
float mask = 1.0 - colorclose(yuv.rgb, keyYUV.rgb, maskRange);
gl_FragColor = max(texColor0 - mask * chromaKey, 0.0) + texColor1 * mask;
}
P5 sketch code:
let theShader;
let cam;
let img;
function preload(){
theShader = loadShader('webcam.vert', 'webcam.frag');
img = loadImage('http://www.quadrochave.com/wp-content/uploads/elementor/thumbs/nodulo_bannersite_ptodu%C3%A7%C3%A3o2-mpe2nvmu8s8o2uqcd7b2oh3mnuv9up05ubby33shz4.png');
}
function setup() {
pixelDensity(1);
createCanvas(windowWidth, windowHeight, WEBGL);
noStroke();
cam = createCapture(VIDEO);
cam.size(windowWidth, windowHeight);
cam.hide();
}
function draw() {
// shader() sets the active shader with our shader
shader(theShader);
// passing cam as a texture
theShader.setUniform('tex0', cam);
theShader.setUniform('tex1', img);
// rect gives us some geometry on the screen
theShader.rect(0,0,width,height);
}
Test on Glitch
Shadertoy chromakey original fragment shader
The mayor issue is, that you didn't specify and set the uniform variable iResolution. But there are some more issues in the shader code (tex0 and tex1 rather than text0 and text1).
Fragment shader:
precision mediump float;
uniform sampler2D tex0;
uniform sampler2D tex1;
uniform vec2 iResolution;
mat4 RGBtoYUV = mat4(0.257, 0.439, -0.148, 0.0,
0.504, -0.368, -0.291, 0.0,
0.098, -0.071, 0.439, 0.0,
0.0625, 0.500, 0.500, 1.0 );
vec4 chromaKey = vec4(0.05, 0.63, 0.14, 1);
vec2 maskRange = vec2(0.005, 0.26);
float colorclose(vec3 yuv, vec3 keyYuv, vec2 tol)
{
float tmp = sqrt(pow(keyYuv.g - yuv.g, 2.0) + pow(keyYuv.b - yuv.b, 2.0));
if (tmp < tol.x)
return 0.0;
else if (tmp < tol.y)
return (tmp - tol.x)/(tol.y - tol.x);
else
return 1.0;
}
void main()
{
vec2 fragPos = gl_FragCoord.xy / iResolution.xy;
vec4 texColor0 = texture2D(tex0, fragPos);
vec4 texColor1 = texture2D(tex1, fragPos);
vec4 keyYUV = RGBtoYUV * chromaKey;
vec4 yuv = RGBtoYUV * texColor0;
float mask = 1.0 - colorclose(yuv.rgb, keyYUV.rgb, maskRange);
gl_FragColor = max(texColor0 - mask * chromaKey, 0.0) + texColor1 * mask;
}
Script:
let theShader;
let cam;
let img;
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
theShader = loadShader('webcam.vert', 'webcam.frag');
img = loadImage('http://www.quadrochave.com/wp-content/uploads/elementor/thumbs/nodulo_bannersite_ptodu%C3%A7%C3%A3o2-mpe2nvmu8s8o2uqcd7b2oh3mnuv9up05ubby33shz4.png');
pixelDensity(1);
noStroke();
cam = createCapture(VIDEO);
cam.size(windowWidth, windowHeight);
cam.hide();
}
function draw() {
// shader() sets the active shader with our shader
shader(theShader);
// passing cam as a texture
theShader.setUniform('tex0', cam);
theShader.setUniform('tex1', img);
theShader.setUniform('iResolution', [width, height]);
// rect gives us some geometry on the screen
rect(0,0,width,height);
}
If the vertex shader provides the texture the coordinate:
// our vertex data
attribute vec3 aPosition;
attribute vec2 aTexCoord;
// lets get texcoords just for fun!
varying vec2 vTexCoord;
void main() {
// copy the texcoords
vTexCoord = aTexCoord;
// copy the position data into a vec4, using 1.0 as the w component
vec4 positionVec4 = vec4(aPosition, 1.0);
positionVec4.xy = positionVec4.xy * 2.0 - 1.0;
// send the vertex information on to the fragment shader
gl_Position = positionVec4;
}
then you can use this coordinate instead of gl_FragCoord.xy / iResolution.xy:
varying vec2 vTexCoord;
// [...]
void main() {
vec2 fragPos = vTexCoord.xy;
// [...]
}

OpenGL 0(84): error C7623: implicit narrowing of type from "vec4" to "float"

I am working on shadows for a Minecraft shader, and im stuck at trying to resolve the following error.
21:51:27.725
[Shaders] Error compiling fragment shader: /shaders/composite.fsh
21:51:27.726
[Shaders] Shader info log: /shaders/composite.fsh
0(84) : error C7623: implicit narrowing of type from "vec4" to "float"
21:51:27.727
[Shaders] Error linking program: 10 (composite)
I know the error is caused by incompatible types, but I'm still not sure how to solve it, so any help is appreciated.
#version 120
const int shadowMapResolution = 2048;
const float shadowDistance = 128;
const float shadowMapBias = 0.85;
const int noiseTextureResolution = 256;
#define SHADOWMAP_BIAS 0.85
uniform sampler2D colortex0;
uniform sampler2D shadowtex0;
uniform sampler2D shadowcolor0;
uniform sampler2D depthtex1;
uniform sampler2D noisetex;
uniform vec3 cameraPosition;
uniform mat4 gbufferModelViewInverse;
uniform mat4 gbufferModelView;
uniform mat4 shadowProjection;
uniform mat4 gbufferProjection;
uniform mat4 gbufferProjectionInverse;
uniform mat4 shadowModelView;
uniform float viewWidth;
uniform float viewHeight;
varying vec4 texcoord;
float depth = 0.5;
vec4 getCameraPosition(in vec2 coord)
{
float getdepth = depth;
vec4 positionNdcSpace = vec4(coord.s * 2.0 - 1.0, coord.t * 2.0 - 1.0, 2.0 * getdepth - 1.0, 1.0);
vec4 positionCameraSpace = gbufferProjectionInverse * positionNdcSpace;
return positionCameraSpace / positionCameraSpace.w;
}
vec4 getWorldSpacePosition(in vec2 coord)
{
vec4 cameraPos = getCameraPosition(coord);
vec4 worldPos = gbufferModelViewInverse * cameraPos;
worldPos.xyz += cameraPosition;
return worldPos;
}
vec3 getShadowSpacePosition(in vec2 coord)
{
vec4 worldSpacePos = getWorldSpacePosition(coord);
worldSpacePos.xyz -= cameraPosition;
vec4 shadowSpacePos = shadowModelView * worldSpacePos;
shadowSpacePos = shadowProjection * shadowSpacePos;
return shadowSpacePos.xyz * 0.5 + 0.5;
}
mat2 getRotationMatrix(in vec2 coord)
{
float rotationAmount = texture2D(
noisetex,
coord * vec2(
viewWidth / noiseTextureResolution,
viewHeight / noiseTextureResolution
)
).r;
return mat2(
cos(rotationAmount), -sin(rotationAmount),
sin(rotationAmount), cos(rotationAmount)
);
}
vec3 getShadows(in vec2 coord)
{
vec3 shadowCoord = getShadowSpacePosition(coord);
mat2 rotationMatrix = getRotationMatrix(coord);
vec3 shadowCol = vec3(0.0);
for (int i = 0; i < 32; i++)
{
vec2 offset = vec2(32 / shadowMapResolution);
offset = rotationMatrix * offset;
float shadowMapSample = texture2D(shadowtex0, shadowCoord.st + offset);
float visibility = step(shadowCoord.z - shadowMapSample, 0.001);
vec3 dayCol = vec3(1.0);
vec3 colorSample = texture2D(shadowcolor0, shadowCoord.st + offset).rgb;
shadowCol += mix(colorSample, dayCol, visibility);
}
return vec3(shadowCol) / 32;
}
vec3 calculateLighting(in vec3 color)
{
vec3 sunLight = getShadows(texcoord.st);
vec3 ambientLight = vec3(0.5, 0.7, 1.0) * 0.5;
return color * (sunLight + ambientLight);
}
void main()
{
depth = texture2D(depthtex1, texcoord.st).r;
vec3 color = texture2D(colortex0, texcoord.st).rbg;
color = calculateLighting(color);
gl_FragData[0] = vec4(color, 1.0);
gl_FragData[1] = vec4(depth);
}
The problem is that texture2D returns a vec4, but you are treating as a float. Read the red component instead
float shadowMapSample = texture2D(shadowtex0, shadowCoord.st + offset).r;

Trying to port a GLSL glass shader to Processing 3.0

EDITED
I am beginner on Processing language and GLSL shaders. I am trying to port a fresnel+cubemap shader for a glass material. But as result my shape ever disappear, instead... :-(
My vertex shader is:
const float Air = 1.0;
const float Glass = 1.51714;
const float Eta = Air / Glass;
const float R0 = ((Air - Glass) * (Air - Glass)) / ((Air + Glass) * (Air + Glass));
uniform mat4 transform;
uniform mat4 modelview;
uniform mat3 normalMatrix;
attribute vec4 vertex;
attribute vec3 normal;
varying vec3 v_reflection;
varying vec3 v_refraction;
varying float v_fresnel;
void main(void){
vec4 t_vertex = modelview * vertex;
vec3 incident = normalize(vec3(t_vertex));
vec3 t_normal = normalMatrix * normal;
v_refraction = refract(incident, t_normal, Eta);
v_reflection = reflect(incident, t_normal);
v_fresnel = R0 + (1.0 - R0) * pow((1.0 - dot(-incident, t_normal)), 5.0);
gl_Position = transform * t_vertex;
}
And the fragment shader:
#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif
uniform samplerCube cubemap;
varying vec3 v_refraction;
varying vec3 v_reflection;
varying float v_fresnel;
void main(void){
vec4 refractionColor = textureCube(cubemap, normalize(v_refraction));
vec4 reflectionColor = textureCube(cubemap, normalize(v_reflection));
gl_FragColor = mix(refractionColor, reflectionColor, v_fresnel);
}
I am testing this shader with the Processing 3.0 sketch bellow (edited), on Android Mode:
PShader shader;
PShape sphere;
void setup() {
fullScreen(P3D);
noStroke();
shader = loadShader("glass.frag.glsl", "glass.vert.glsl");
openCubeMap("posx.png", "negx.png", "posy.png", "negy.png", "posz.png", "negz.png");
shader.set("cubemap", 1);
sphere = createShape(SPHERE, 120);
sphere.setFill(color(-1, 50));
}
void draw() {
background(0);
directionalLight(102, 102, 102, 0, 0, -1);
lightSpecular(204, 204, 204);
directionalLight(102, 102, 102, 0, 1, -1);
specular(100, 150, 150);
translate(width / 2, height / 2);
shader(shader);
shape(sphere);
}
void openCubeMap(String posX, String negX, String posY, String negY, String posZ, String negZ) {
PGL pgl = beginPGL();
// create the OpenGL-based cubeMap
IntBuffer envMapTextureID = IntBuffer.allocate(1);
pgl.genTextures(1, envMapTextureID);
pgl.activeTexture(PGL.TEXTURE1);
pgl.enable(PGL.TEXTURE_CUBE_MAP);
pgl.bindTexture(PGL.TEXTURE_CUBE_MAP, envMapTextureID.get(0));
pgl.texParameteri(PGL.TEXTURE_CUBE_MAP, PGL.TEXTURE_WRAP_S, PGL.CLAMP_TO_EDGE);
pgl.texParameteri(PGL.TEXTURE_CUBE_MAP, PGL.TEXTURE_WRAP_T, PGL.CLAMP_TO_EDGE);
pgl.texParameteri(PGL.TEXTURE_CUBE_MAP, PGL.TEXTURE_WRAP_R, PGL.CLAMP_TO_EDGE);
pgl.texParameteri(PGL.TEXTURE_CUBE_MAP, PGL.TEXTURE_MIN_FILTER, PGL.LINEAR);
pgl.texParameteri(PGL.TEXTURE_CUBE_MAP, PGL.TEXTURE_MAG_FILTER, PGL.LINEAR);
//Load in textures
String[] textureNames = { posX, negX, posY, negY, posZ, negZ };
for (int i=0; i<textureNames.length; i++) {
PImage texture = loadImage(textureNames[i]);
int w = texture.width;
int h = texture.height;
texture.loadPixels();
pgl.texImage2D(PGL.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, PGL.RGBA, w, h, 0, PGL.RGBA, PGL.UNSIGNED_BYTE, IntBuffer.wrap(texture.pixels));
}
endPGL();
}
And I am using this images to build the cubemap.
Someone know how I can make this work?
Problem is not in your code but in your data.
OpenGL requires that all textures used by the cubemap have the same dimensions, and that the textures be square otherwise it will refuse to load it.
I checked your PNGs and this is not the case, they all have the same dimension but they are not square (255x230).
Also for Android it may be required that the texture dimensions be a power of 2 (128, 256, 512 ...)
So I tested resizing all the textures to 256x256 pixels and now your sample works :

GLSL Texture Size

I have a problem with my fragment shader.
I want to get the size of a texture (which is loaded from an image).
I know that it is possible to use textureSize(sampler) to get an ivec2 which contains the texture size. But i don't know why this isn't working (it doesn't compile):
#version 120
uniform sampler2D tex;
float textureSize;
float texelSize;
void main()
{
textureSize = textureSize(tex).x;//first line
//textureSize = 512.0;//if i set the above line as comment and use this one the shader compiles.
texelSize = 1.0 / textureSize;
vec4 color = texture2D(tex,gl_TexCoord[0].st);
gl_FragColor = color * gl_Color;
}
Th problem was that my GLSL version was to low (implemented in 1.30) and that i was missing a parameter.
Here the working version:
#version 130
uniform sampler2D tex;
float textureSize;
float texelSize;
void main()
{
ivec2 textureSize2d = textureSize(tex,0);
textureSize = float(textureSize2d.x);
texelSize = 1.0 / textureSize;
vec4 color = texture2D(tex,gl_TexCoord[0].st);
gl_FragColor = color * gl_Color;
}