Increase the intensity of texture in shader code - OpenGL

亡梦爱人 提交于 2019-12-11 13:16:36

问题


How can I increase the intensity of an image using opengl shadercode? The purpose is that the resulted image should look more brighter than actual image. Found a related link here. But it is for android.

private void CreateShaders()
{
    /***********Vert Shader********************/
    vertShader = GL.CreateShader(ShaderType.VertexShader);
    GL.ShaderSource(vertShader, @"
        attribute vec3 a_position;
        varying vec2 vTexCoord;
        void main() {
            vTexCoord = (a_position.xy + 1) / 2;
            gl_Position = vec4(a_position,1);
        }");
    GL.CompileShader(vertShader);

    /***********Frag Shader ****************/
    fragShader = GL.CreateShader(ShaderType.FragmentShader);
    GL.ShaderSource(fragShader, @"
        precision highp float;
        uniform sampler2D sTexture;
        varying vec2 vTexCoord;
        vec3 RGBtoHSV(in vec3 RGB)
        {
            vec4 P = (RGB.g < RGB.b) ? vec4(RGB.bg, -1.0, 2.0 / 3.0) : vec4(RGB.gb, 0.0, -1.0 / 3.0);
            vec4 Q = (RGB.r < P.x) ? vec4(P.xyw, RGB.r) : vec4(RGB.r, P.yzx);
            float C = Q.x - min(Q.w, Q.y);
            float H = abs((Q.w - Q.y) / (6.0 * C + Epsilon) + Q.z);
            vec3 HCV = vec3(H, C, Q.x);
            float S = HCV.y / (HCV.z + Epsilon);
            return vec3(HCV.x, S, HCV.z);
        }
        vec3 HSVtoRGB(in vec3 HSV)
        {
            float H = HSV.x;
            float R = abs(H * 6.0 - 3.0) - 1.0;
            float G = 2.0 - abs(H * 6.0 - 2.0);
            float B = 2.0 - abs(H * 6.0 - 4.0);
            vec3 RGB = clamp(vec3(R, G, B), 0.0, 1.0);
            return ((RGB - 1.0) * HSV.y + 1.0) * HSV.z;
        }

        void main ()
        {
            vec4  color = texture2D (sTexture, vTexCoord);
            float u_saturate=0.9;
            vec3 col_hsv = RGBtoHSV(color.rgb);
            col_hsv.y *= (u_saturate * 2.0);
            vec3 col_rgb = HSVtoRGB(col_hsv.rgb);
            gl_FragColor = vec4(col_rgb.rgb, color.a);
        }");
    GL.CompileShader(fragShader);
}

回答1:


One possibility is to convert the RGB color to a HSV (hue, saturation, value). Change the saturation and convert it back to a RGB value.

A HLSL implementation to convert between RGB and HSV can be found at RGB to HSV/HSL/HCY/HCL in HLSL.

The ported code from HLSL to GLSL is:

RGB to HSV:

const float Epsilon = 1e-10;

vec3 RGBtoHSV(in vec3 RGB)
{
    vec4  P   = (RGB.g < RGB.b) ? vec4(RGB.bg, -1.0, 2.0/3.0) : vec4(RGB.gb, 0.0, -1.0/3.0);
    vec4  Q   = (RGB.r < P.x) ? vec4(P.xyw, RGB.r) : vec4(RGB.r, P.yzx);
    float C   = Q.x - min(Q.w, Q.y);
    float H   = abs((Q.w - Q.y) / (6.0 * C + Epsilon) + Q.z);
    vec3  HCV = vec3(H, C, Q.x);
    float S   = HCV.y / (HCV.z + Epsilon);
    return vec3(HCV.x, S, HCV.z);
}

HSV to RGB:

vec3 HSVtoRGB(in vec3 HSV)
{
    float H   = HSV.x;
    float R   = abs(H * 6.0 - 3.0) - 1.0;
    float G   = 2.0 - abs(H * 6.0 - 2.0);
    float B   = 2.0 - abs(H * 6.0 - 4.0);
    vec3  RGB = clamp( vec3(R,G,B), 0.0, 1.0 );
    return ((RGB - 1.0) * HSV.y + 1.0) * HSV.z;
}

The code can be integrated in your fragment shader with ease. u_saturate is a value in the range [0.0, 1.0]. 0.5 means that the image is kept as it is. It u_saturate is greater 0.5 the image is saturated and if it is less than 0.5 the image is bleached:

void main ()
{
    vec4 color  = texture2D (sTexture, vTexCoord);

    vec3 col_hsv = RGBtoHSV(texColor.rgb);
    col_hsv.y *= (u_saturate * 2.0);
    vec3 col_rgb = HSVtoRGB(col_hsv.rgb);

    gl_FragColor = vec4(col_rgb.rgb, color.a);
}

See the WebGL example, which demonstrates the effect:

(function loadscene() {

var gl, canvas, prog, bufObj = {}, textureObj, maskTextureObj;

function render(deltaMS) {

    var saturate = document.getElementById( "saturate" ).value / 100.0;

    gl.viewport( 0, 0, vp_size[0], vp_size[1] );
    gl.enable( gl.DEPTH_TEST );
    gl.clearColor( 0.0, 0.0, 0.0, 1.0 );
    gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT );
    var texUnit = 0;
    gl.activeTexture( gl.TEXTURE0 + texUnit );
    gl.bindTexture( gl.TEXTURE_2D, textureObj );
    ShProg.Use( progDraw );
    ShProg.SetI1( progDraw, "u_texture", texUnit );
    ShProg.SetF2( progDraw, "u_vp_size", vp_size );
    ShProg.SetF1( progDraw, "u_saturate", saturate );
    VertexBuffer.Draw( bufRect );

    requestAnimationFrame(render);
}  

function initScene() {

    canvas = document.getElementById( "texture-canvas");
    gl = canvas.getContext( "experimental-webgl" );
    //gl = canvas.getContext( "webgl2" );
    if ( !gl )
      return;

    var texCX = 128;
    var texCY = 128;
    var texPlan = [];
    for (ix = 0; ix < texCX; ++ix) {
        for (iy = 0; iy < texCY; ++iy) {
            var val_x = Math.sin( Math.PI * 6.0 * ix / texCX )
            var val_y = Math.sin( Math.PI * 6.0 * iy / texCY )
            texPlan.push( 128 + 127 * val_x, 63, 128 + 127 * val_y, 255 );
        }
    }
    
    textureObj = Texture.LoadTexture2D( "https://raw.githubusercontent.com/Rabbid76/graphics-snippets/master/resource/texture/supermario.jpg" );
      
    progDraw = ShProg.Create( 
      [ { source : "draw-shader-vs", stage : gl.VERTEX_SHADER },
        { source : "draw-shader-fs", stage : gl.FRAGMENT_SHADER }
      ] );
    progDraw.inPos = gl.getAttribLocation( progDraw.progObj, "inPos" );
    if ( progDraw.progObj == 0 )
        return;

    bufRect = VertexBuffer.Create(
    [ { data :  [ -1, -1, 1, -1, 1, 1, -1, 1 ], attrSize : 2, attrLoc : progDraw.inPos } ],
      [ 0, 1, 2, 0, 2, 3 ] );

    window.onresize = resize;
    resize();
    requestAnimationFrame(render);
}

function resize() {
    //vp_size = [gl.drawingBufferWidth, gl.drawingBufferHeight];
    vp_size = [window.innerWidth, window.innerHeight]
    //vp_size = [256, 256]
    canvas.width = vp_size[0];
    canvas.height = vp_size[1];
}

var ShProg = {
Create: function (shaderList) {
    var shaderObjs = [];
    for (var i_sh = 0; i_sh < shaderList.length; ++i_sh) {
        var shderObj = this.Compile(shaderList[i_sh].source, shaderList[i_sh].stage);
        if (shderObj) shaderObjs.push(shderObj);
    }
    var prog = {}
    prog.progObj = this.Link(shaderObjs)
    if (prog.progObj) {
        prog.attrInx = {};
        var noOfAttributes = gl.getProgramParameter(prog.progObj, gl.ACTIVE_ATTRIBUTES);
        for (var i_n = 0; i_n < noOfAttributes; ++i_n) {
            var name = gl.getActiveAttrib(prog.progObj, i_n).name;
            prog.attrInx[name] = gl.getAttribLocation(prog.progObj, name);
        }
        prog.uniLoc = {};
        var noOfUniforms = gl.getProgramParameter(prog.progObj, gl.ACTIVE_UNIFORMS);
        for (var i_n = 0; i_n < noOfUniforms; ++i_n) {
            var name = gl.getActiveUniform(prog.progObj, i_n).name;
            prog.uniLoc[name] = gl.getUniformLocation(prog.progObj, name);
        }
    }
    return prog;
},
AttrI: function (prog, name) { return prog.attrInx[name]; },
UniformL: function (prog, name) { return prog.uniLoc[name]; },
Use: function (prog) { gl.useProgram(prog.progObj); },
SetI1: function (prog, name, val) { if (prog.uniLoc[name]) gl.uniform1i(prog.uniLoc[name], val); },
SetF1: function (prog, name, val) { if (prog.uniLoc[name]) gl.uniform1f(prog.uniLoc[name], val); },
SetF2: function (prog, name, arr) { if (prog.uniLoc[name]) gl.uniform2fv(prog.uniLoc[name], arr); },
SetF3: function (prog, name, arr) { if (prog.uniLoc[name]) gl.uniform3fv(prog.uniLoc[name], arr); },
SetF4: function (prog, name, arr) { if (prog.uniLoc[name]) gl.uniform4fv(prog.uniLoc[name], arr); },
SetM33: function (prog, name, mat) { if (prog.uniLoc[name]) gl.uniformMatrix3fv(prog.uniLoc[name], false, mat); },
SetM44: function (prog, name, mat) { if (prog.uniLoc[name]) gl.uniformMatrix4fv(prog.uniLoc[name], false, mat); },
Compile: function (source, shaderStage) {
    var shaderScript = document.getElementById(source);
    if (shaderScript)
        source = shaderScript.text;
    var shaderObj = gl.createShader(shaderStage);
    gl.shaderSource(shaderObj, source);
    gl.compileShader(shaderObj);
    var status = gl.getShaderParameter(shaderObj, gl.COMPILE_STATUS);
    if (!status) alert(gl.getShaderInfoLog(shaderObj));
    return status ? shaderObj : null;
},
Link: function (shaderObjs) {
    var prog = gl.createProgram();
    for (var i_sh = 0; i_sh < shaderObjs.length; ++i_sh)
        gl.attachShader(prog, shaderObjs[i_sh]);
    gl.linkProgram(prog);
    status = gl.getProgramParameter(prog, gl.LINK_STATUS);
    if ( !status ) alert(gl.getProgramInfoLog(prog));
    return status ? prog : null;
} };

var VertexBuffer = {
Create: function(attribs, indices, type) {
    var buffer = { buf: [], attr: [], inx: gl.createBuffer(), inxLen: indices.length, primitive_type: type ? type : gl.TRIANGLES };
    for (var i=0; i<attribs.length; ++i) {
        buffer.buf.push(gl.createBuffer());
        buffer.attr.push({ size : attribs[i].attrSize, loc : attribs[i].attrLoc, no_of: attribs[i].data.length/attribs[i].attrSize });
        gl.bindBuffer(gl.ARRAY_BUFFER, buffer.buf[i]);
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array( attribs[i].data ), gl.STATIC_DRAW);
    }
    gl.bindBuffer(gl.ARRAY_BUFFER, null);
    if ( buffer.inxLen > 0 ) {
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer.inx);
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( indices ), gl.STATIC_DRAW);
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
    }
    return buffer;
},
Draw: function(bufObj) {
    for (var i=0; i<bufObj.buf.length; ++i) {
        gl.bindBuffer(gl.ARRAY_BUFFER, bufObj.buf[i]);
        gl.vertexAttribPointer(bufObj.attr[i].loc, bufObj.attr[i].size, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray( bufObj.attr[i].loc);
    }
    if ( bufObj.inxLen > 0 ) {
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, bufObj.inx);
        gl.drawElements(bufObj.primitive_type, bufObj.inxLen, gl.UNSIGNED_SHORT, 0);
        gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, null );
    }
    else
        gl.drawArrays(bufObj.primitive_type, 0, bufObj.attr[0].no_of );
    for (var i=0; i<bufObj.buf.length; ++i)
        gl.disableVertexAttribArray(bufObj.attr[i].loc);
    gl.bindBuffer( gl.ARRAY_BUFFER, null );
} };

var Texture = {};
Texture.HandleLoadedTexture2D = function( image, texture, flipY ) {
    gl.activeTexture( gl.TEXTURE0 );
    gl.bindTexture( gl.TEXTURE_2D, texture );
    gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, flipY != undefined && flipY == true );
    gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image );
    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR );
    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR );
    gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT );
  	gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT );
    gl.bindTexture( gl.TEXTURE_2D, null );
    return texture;
}
Texture.LoadTexture2D = function( name ) {
    var texture = gl.createTexture();
    texture.image = new Image();
    texture.image.setAttribute('crossorigin', 'anonymous');
    texture.image.onload = function () {
        Texture.HandleLoadedTexture2D( texture.image, texture, false )
    }
    texture.image.src = name;
    return texture;
}

initScene();

})();
html,body { margin: 0; overflow: hidden; }
#gui-left { position : absolute; top : 0; left : 0; color: #40f040; }
<script id="draw-shader-vs" type="x-shader/x-vertex">
    precision mediump float;

    attribute vec2 inPos;
    varying   vec2 vertPos;
    uniform   vec2 u_vp_size;

    void main()
    {
        vec2 scale  = u_vp_size.x > u_vp_size.y ? vec2(u_vp_size.y/u_vp_size.x, 1.0) : vec2(1.0, u_vp_size.x/u_vp_size.y);
        vertPos     = inPos;
        gl_Position = vec4( inPos * scale, 0.0, 1.0 );
    }
</script>

<script id="draw-shader-fs" type="x-shader/x-fragment">
    precision mediump float;

    varying vec2      vertPos;
    uniform sampler2D u_texture;
    uniform float     u_saturate;

    const float Epsilon = 1e-10;
 
    vec3 RGBtoHSV(in vec3 RGB)
    {
        vec4  P   = (RGB.g < RGB.b) ? vec4(RGB.bg, -1.0, 2.0/3.0) : vec4(RGB.gb, 0.0, -1.0/3.0);
        vec4  Q   = (RGB.r < P.x) ? vec4(P.xyw, RGB.r) : vec4(RGB.r, P.yzx);
        float C   = Q.x - min(Q.w, Q.y);
        float H   = abs((Q.w - Q.y) / (6.0 * C + Epsilon) + Q.z);
        vec3  HCV = vec3(H, C, Q.x);
        float S   = HCV.y / (HCV.z + Epsilon);
        return vec3(HCV.x, S, HCV.z);
    }

    vec3 HSVtoRGB(in vec3 HSV)
    {
        float H   = HSV.x;
        float R   = abs(H * 6.0 - 3.0) - 1.0;
        float G   = 2.0 - abs(H * 6.0 - 2.0);
        float B   = 2.0 - abs(H * 6.0 - 4.0);
        vec3  RGB = clamp( vec3(R,G,B), 0.0, 1.0 );
        return ((RGB - 1.0) * HSV.y + 1.0) * HSV.z;
    }
    
    void main()
    {
        vec2 texCoord = vec2( vertPos.s, -vertPos.t ) * 0.5 + 0.5;
        vec3 texColor = texture2D( u_texture, texCoord.st ).rgb;

        vec3 col_hsv = RGBtoHSV(texColor.rgb);
        col_hsv.y *= (u_saturate * 2.0); 
        vec3 col_rgb = HSVtoRGB(col_hsv.rgb);

        gl_FragColor  = vec4( col_rgb.rgb, 1.0 );
    }
</script>

<div id="gui-left">
  <table>
  <tr><td>saturate</td><td><input type="range" id="saturate" min="0" max="100" value="50"/></td></tr>
  </table>
</div>

<canvas id="texture-canvas" style="border: none"></canvas>



回答2:


If you just want to increase the intensity of a single Color, in the pixel shader Code

vec4  color = texture2D (sTexture, vTexCoord);
color.g = color.g * 1.2;
gl_FragColor = color;

And green will be 1.2 times brighter. If you want to change stuffs like the intensity of all the colors, then you need to look at stuffs like the HSL color space. I answered a question about that: GLSL shader to boost the color



来源:https://stackoverflow.com/questions/53879537/increase-the-intensity-of-texture-in-shader-code-opengl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!