圆角矩形shader

在游戏中,有时需要对一张矩形图片进行切割,绘制成圆角矩形。

circelrect.vert

attribute vec4 a_position;
attribute vec4 a_normal;
attribute vec4 a_color;
attribute vec2 a_texCoord0;

uniform mat4 u_projTrans;

varying vec4 v_color;
varying vec2 v_texCoords;

void main() {
    v_color = vec4(0, 0, 0, 0);
    v_texCoords = a_texCoord0;
    gl_Position = u_projTrans * a_position;
}

circlerect.frag

#ifdef GL_ES
precision mediump float;
#endif

varying vec2 v_texCoords;
uniform sampler2D u_texture;

varying vec4 v_color;

uniform float r;


bool isOut(float x, float y, float cx, float cy, float r){
    bool flag1 = (cx<0.5f && x<cx) || (cx>0.5f && x>cx);
    bool flag2 = (cy<0.5f && y<cy) || (cy>0.5f && y>cy);
    float dis = (x-cx)*(x-cx) + (y-cy)*(y-cy);
    if(flag1 && flag2 && dis>r*r){
        return true;
    }
    return false;
}


void main() {
    vec4 texColor = texture2D(u_texture, v_texCoords);
    
    float x = v_texCoords.x;
    float y = v_texCoords.y;
    
    float rate = 1f;
    
    if(isOut(x, y, r, r, r)) rate = 0f;
    if(isOut(x, y, r, 1-r, r)) rate = 0f;
    if(isOut(x, y, 1-r, r, r)) rate = 0f;
    if(isOut(x, y, 1-r, 1-r, r)) rate = 0f;
    
    
    gl_FragColor = vec4(texColor.rgb, rate*texColor.a);
}

gdx程序

package com.fxb.gdx.example;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;

public class Test014_MaskShader extends ApplicationAdapter{

    SpriteBatch batch;
    Texture texture;
    ShaderProgram shader;
    
    int[][] maskss;
    int[] masks;
    
    public void create() {
        super.create();
        batch = new SpriteBatch();
        texture = new Texture(Gdx.files.internal("data/pic.jpg"));
        
//        shader = new ShaderProgram(    Gdx.files.internal("shader/mask.vert").readString(), 
//                                    Gdx.files.internal("shader/mask.frag").readString() );
        
        shader = new ShaderProgram(    Gdx.files.internal("shader/circlerect.vert").readString(), 
                                    Gdx.files.internal("shader/circlerect.frag").readString() );
        
        
        batch.setShader(shader);
        
        maskss = new int[10][10];
        for(int i=0; i<maskss.length; ++i){
            for(int j=0; j<maskss[i].length; ++j){
                maskss[i][j] = 0;
            }
        }
        
        maskss[1][2] = 1;
        maskss[5][6] = 1;
        
        masks = new int[100];
        setMask(1, 2);
        setMask(5, 6);
        
//        shader.setUniformf("maskX", 0.2f);
//        shader.setUniformf("maskY", 0.3f);    
        
        Gdx.input.setInputProcessor(adapter);
    }
    
    private void setMask(int xIndex, int yIndex){
        maskss[xIndex][yIndex] = 1;
        
        masks[yIndex*10+xIndex] = 1;
    }
    
//    float maskX = 0.3f, maskY = 0.4f;
//    float[] maskXs = {0.3f, 0.9f};
//    float[] maskYs = {0.4f, 0.9f};
    
    float[] maskXs = new float[10];
    float[] maskYs = new float[10];
    
    float r = 0.05f;
    float step = 0.01f;
    float rate = 1f;
    public void render() {
        super.render();
//        Gdx.gl.glClearColor(0.3f, 0.3f, 0.3f, 1f);
        Gdx.gl.glClearColor(0f, 0f, 0f, 1f);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        
//        uniform float maskX;
//        uniform float maskY;
        
        batch.setShader(shader);
        batch.begin();
//        shader.setUniformf("maskX", maskX);
//        shader.setUniformf("maskY", maskY);
        
//        shader.setUniform1fv("maskXs", maskXs, 0, 10);
//        shader.setUniform1fv("maskYs", maskYs, 0, 10);
        
        shader.setUniformf("r", r);
        batch.draw(texture, 100, 100); 
        batch.end();
        
        r += step*rate;
        if(r >=0.45f){
            rate = -1f;
        }
        else if(r <= 0f){
            rate = 1f;
        }
    }
    
    public void dispose() {
        super.dispose();
        
        
//        uniform float[] maskXs;
//        uniform float[] maskYs;
//
//        void main() {
//            vec4 texColor = texture2D(u_texture, v_texCoords);
//            
//            float x = v_texCoords.x;
//            float y = 1f - v_texCoords.y;
//            
//            float rate = 1f;
//            for(GLint i=0; i<2; ++i){
//                float maskX = maskXs[i];
//                float maskY = maskYs[i];
//                if(x>maskX-0.02f && x<maskX+0.02f && y>maskY-0.02f && y<maskY+0.02f){
//                    rate = 0f;
//                }    
//            }
//
//            
//            gl_FragColor = vec4(texColor.rgb, texColor.a*rate);
//        }
        
    }

    
    private InputAdapter adapter = new InputAdapter(){

        public int changeY(int screenY){
            return 480-screenY;
        }
        
        public boolean touchDown(int screenX, int screenY, int pointer,int button) {
            screenY = changeY(screenY);
            
            float curX = screenX-100, curY = screenY-100;
            if(curX>0 && curX<texture.getWidth() && curY>0 && curY<texture.getHeight()){
//                maskX = curX/texture.getWidth();
//                maskY = curY/texture.getHeight();
                
//                maskXs[0] = maskXs[1];
//                maskYs[0] = maskYs[1];
                
                for(int i=0; i<maskXs.length-1; ++i){
                    maskXs[i] = maskXs[i+1];
                    maskYs[i] = maskYs[i+1];
                }
                
                maskXs[maskXs.length-1] = curX/texture.getWidth();
                maskYs[maskYs.length-1] = curY/texture.getHeight();
                
            }
            
            return super.touchDown(screenX, screenY, pointer, button);
        }

        public boolean touchUp(int screenX, int screenY, int pointer, int button) {
            return super.touchUp(screenX, screenY, pointer, button);
        }

        public boolean touchDragged(int screenX, int screenY, int pointer) {
            return super.touchDragged(screenX, screenY, pointer);
        }
        
    };
}

运行结果:

原文地址:https://www.cnblogs.com/MiniHouse/p/5261691.html