还附加了来自设备的屏幕截图, 你可以帮我解决这个问题吗? 其Android KitKat版本
public class Balloon
{
private final String vertexShaderCode =
// This matrix member variable provides a hook to manipulate
// the coordinates of the objects that use this vertex shader
"attribute vec4 vPosition;" +
"void main() {" +
"gl_PointSize = 5.0; "+
" gl_Position = vPosition;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
private FloatBuffer vertexBuffer;
private final int mProgram;
private int mPositionHandle;
private int mColorHandle;
private int mMVPMatrixHandle;
private float[] data = new float[126];
// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 3;
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 0.0f };
/**
* Sets up the drawing object data for use in an OpenGL ES context.
*/
public Balloon() {
// prepare shaders and OpenGL program
int vertexShader = MyGLRenderer.loadShader(
GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = MyGLRenderer.loadShader(
GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
mProgram = GLES20.glCreateProgram();
// create empty OpenGL Program
GLES20.glAttachShader(mProgram, vertexShader);
// add the vertex shader to program
GLES20.glAttachShader(mProgram, fragmentShader);
// add the fragment shader to program
GLES20.glLinkProgram(mProgram);
// create OpenGL program executables
}
private void FillBalloon(float x1,float y1,float r1)
{
int i=0,j=0;
float angle = 0;
float twicePI = (float)2.0 * (float)3.1415926;
float angle_stepsize = 0.1f;
// go through all angles from 0 to 2 * PI radians
for(;angle < twicePI;angle = (angle + angle_stepsize))
{
// calculate x, y from a vector with known length and angle
data[j++] = x1 + r1 * (float)Math.cos(angle);
data[j++] = y1 + r1 * (float)Math.sin(angle);
}
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(
// (number of coordinate values * 4 bytes per float)
j * 4);
// use the device hardware's native byte order
bb.order(ByteOrder.nativeOrder());
// create a floating point buffer from the ByteBuffer
vertexBuffer = bb.asFloatBuffer();
// add the coordinates to the FloatBuffer
vertexBuffer.put(data);
// set the buffer to read the first coordinate
vertexBuffer.position(0);
}
/**
* Encapsulates the OpenGL ES instructions for drawing this shape.
*
*/
public void draw() {
// Add program to OpenGL environment
GLES20.glUseProgram(mProgram);
float posX = 0.0f,posY = 0.0f,radius =0.2f;
FillBalloon(posX, posY, radius);
// get handle to vertex shader's vPosition member
mPositionHandle =
GLES20.glGetAttribLocation(mProgram,"vPosition");
// Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray(mPositionHandle);
// Prepare the balloon coordinate data
GLES20.glVertexAttribPointer(mPositionHandle, 2, GLES20.GL_FLOAT, false, 0, vertexBuffer);
// get handle to fragment shader's vColor member
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
// Set color for drawing the triangle
GLES20.glUniform4fv(mColorHandle, 1, color, 0);
MyGLRenderer.checkGlError("mColorHandle");
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 63);
// Disable vertex array
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}
还附有设备屏幕截图, 你可以帮我解决这个问题吗? 它的Android KitKat版本
答案 0 :(得分:1)
这是预期的行为。每个轴的openGL默认坐标系为[-1,1]。这意味着最左边的点将包含x=-1
,最右边x=1
,最顶层y=1
和最底层y=-1
。现在,根据您的屏幕比例,结果将具有相同的拉伸比率。
您可以随意处理场景以绘制形状。一种方法是在生成顶点数据时对其进行缩放,但我强烈建议您不要这样做,因为模型顶点数据应该按照它们的意图。另一种方法是简单地创建一个方形表面视图,然后限制您的绘图表面,因此它不是最好的方法。另一种方法是使用视口并设置一个矩形,您可以在其中绘制您的形状,其中可能没问题,但您需要记住将其设置回全宽和高度。然后有矩阵......
使用矩阵定义坐标系。对于2D,最好的方法通常是使用Ortho
,它使用边界参数(左,上,下,右),然后可以设置为你想要的任何东西。例如,您可以使用视图坐标(left = 0
,right = viewWidth
,top = 0
,bottom = viewHeight
),或者您可以将系统标准化为零,并选择哪个边框的值应为{ {1}}:对于水平规范化,您将拥有(1.0
,left = -1
,right = 1
,top = viewHeight/viewWidth
)和垂直(bottom = -viewHeight/viewWidth
,{{1} },left = -viewWidth/viewHeight
,right = viewWidth/viewHeight
)。
答案 1 :(得分:0)
要使气球看起来像圆圈,请添加一个浮点(我们称之为X_SCALE)作为绘制参数:
public void draw(float X_SCALE) {
...
FillBaloon(posX, posY, radius, X_SCALE);
...
}
然后将您的绘制时间x坐标乘以FillBaloon(...)中的比例因子:
data[j++] = x1 + X_SCALE * r1 * (float)Math.cos(angle);
并在渲染器绘制(X_SCALE)调用中设置比例因子:
X_SCALE = (float)MyGLSurfaceView.getHeight()/(float)MyGLSurfaceView.getWidth();
myBaloon.draw(X_SCALE);
更好的方法是在onSurfaceCreated(...)中设置一次X_SCALE,并且每次在onSurfaceChanged(...)中调整表面大小。
最后一件事:你可以通过在显式初始化中使用“f”后缀来避免将双精度转换为浮点数:
float twicePI = 6.28318530717959f;