【问题标题】:How to achieve brightness + contrast in WebGL?如何在 WebGL 中实现亮度+对比度?
【发布时间】:2016-06-20 23:07:17
【问题描述】:

我正在尝试应用类似于this example 的窗口级别,将鼠标拖到图像上以查看亮度+对比度效果。

但我想使用 WebGL 来达到同样的效果,因为 GPU 处理它们的速度比 CPU 快。

这是我所做的:

顶点着色器:

attribute vec3 attrVertexPos;
attribute vec2 attrTextureCoord;

varying highp vec2 vTextureCoord;

void main(void) {
    gl_Position = vec4(attrVertexPos, 0.81);
    vTextureCoord = attrTextureCoord;
}

片段着色器:

#ifdef GL_ES
    precision highp float;
#endif

varying highp vec2 vTextureCoord;

uniform sampler2D uImage;
uniform float brightnessFactor;
uniform float contrastFactor;

void main(void) {
    gl_FragColor = texture2D(uImage, vTextureCoord) *(brightnessFactor/contrastFactor);
}

但根据上面给出的链接,它不能按预期工作。

这是 Javascript 代码:

var isMouseDown = false;

document.getElementById('canvas').onmousedown = function() { isMouseDown = true  };
document.getElementById('canvas').onmouseup   = function() { isMouseDown = false };
document.getElementById('canvas').onmousemove = function(e) {
    if (isMouseDown) {
        var intWidth = $('canvas').innerWidth();
        var intHeight = $('canvas').innerHeight();
        var x = (e.clientX/intWidth)*100;
        var y = (e.clientY/intHeight)*100;

        console.log(x/10 + ' :: ' + y/10);

        brightnessVal = x/10;
        gl.uniform1f(gl.getUniformLocation(program, "contrastFactor"), brightnessVal);
        contrastVal = y/10;
        gl.uniform1f(gl.getUniformLocation(program, "brightnessFactor"), contrastVal);
    }
};

【问题讨论】:

    标签: opengl-es webgl


    【解决方案1】:

    区别在于像素操作。您只是乘以一个系数(而且,您使用的系数的名称不正确),在链接的示例中,正在发生一些更复杂的事情。源图像中的某些颜色范围(由其中心和宽度描述)扩展到完整的 [0,1] 范围:

    newColor = (oldColor - rangeCenter) / rangeWidth + 0.5
    

    为什么这样做超出了我的知识范围(该页面是医学影像库的示例,我对此一无所知)。尽管如此,我还是设法将公式移植到您的代码中。一、片段着色器变化:

    #ifdef GL_FRAGMENT_PRECISION_HIGH
        precision highp float;
    #else
        precision mediump float;
    #endif
    
    varying highp vec2 vTextureCoord;
    uniform sampler2D uImage;
    
    // New uniforms
    uniform float rangeCenter;
    uniform float rangeWidth;
    
    void main(void) {
        vec3 c = texture2D(uImage, vTextureCoord).rgb;
        gl_FragColor = vec4(
            // The above formula, clamped to [0, 1]
            clamp((c - windowCenter) / windowWidth + 0.5, 0.0, 1.0),
            // Also, let's not screw alpha
            1
        );
    }
    

    至于 JavaScript,我冒昧地让它更接近链接示例:

    var isMouseDown = false,
        // Initially we set "equality" colour mapping
        rangeCenter = 0.5,
        ragneWidth = 1,
        lastX, lastY;
    
    document.getElementById('canvas').onmousedown = function(e) {
        lastX = e.clientX;
        lastY = e.clientY;
        isMouseDown = true
    };
    document.getElementById('canvas').onmouseup = function() {
        isMouseDown = false
    };
    document.getElementById('canvas').onmousemove = function(e) {
        if (isMouseDown) {
            var intWidth = $('canvas').innerWidth();
            var intHeight = $('canvas').innerHeight();
    
            // Change params according to cursor coords delta
            rangeWidth += (e.clientX - lastX) / intWidth;
            rangeCenter += (e.clientY - lastY) / intHeight;
    
            gl.uniform1f(
                gl.getUniformLocation(program, "rangeWidth"),
                rangeWidth
            );
    
            gl.uniform1f(
                gl.getUniformLocation(program, "rangeCenter"),
                rangeCenter
            );
    
            lastX = e.clientX;
            lastY = e.clientY;
        }
    };
    

    旧答案:

    问题是,根据您的代码,您没有重绘 mousemove 事件后的图片。只需插入一个绘图调用(或几个 绘制调用)在设置制服后使用适当的参数。为了 例如,它可能看起来像这样:

    document.getElementById('canvas').onmousemove = function(e) {
        if (isMouseDown) {
            // your code
    
            gl.drawArrays(/* params, e.g gl.TRIANGLES, 0 and vertex count */); 
        }
    };
    

    更好的方法是使用requestAnimationFrame 回调 重绘。为此,请定义一个 draw 函数,该函数将绘制 呼叫您并使用它作为requestAnimationFrame 回调:

    function draw () {
        /* your draw calls here */
    }
    
    document.getElementById('canvas').onmousemove = function(e) {
        if (isMouseDown) {
            // your code
    
            requestAnimationFrame(draw);
        }
    };
    

    附:另外,我很感兴趣,这个#ifdef GL_ES 是从哪里来的?根据GL_ES 宏设置highp 精度是不正确。根据标准,硬件不必支持它。正确的方法是:

    #ifdef GL_FRAGMENT_PRECISION_HIGH
        precision highp float;
    #else
        precision mediump float;
    #endif
    

    【讨论】:

    • 实际上,我已经实现了 requestAnimationFrame,它给了我错误的结果: var render = function () { gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0); requestAnimationFrame(render); }
    • 好的,您能详细说一下:您看到的图像有什么问题吗?你能链接一个页面或 jsfiddle 以便我仔细看看吗?
    • 当然,让我为你制作一个小提琴
    • 请检查jsfiddle.net/Subhasish2015/rbmqqp2v/1,但不知何故,在将其保存为图像后,它并没有从rawgit.com/chafey/cornerstone/master/example/windowlevel/… 获取大脑图像,但您可以尝试使用这两个图像并比较结果
    • @SubhasishDash 修改了答案。
    猜你喜欢
    • 2015-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多