- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试使用 gles 2 在 android 中绘制一些 3d 线。但它导致了一些奇怪的效果。当我旋转场景/相机时会发生闪烁。但不仅如此,还有一些随机绘制的 2d 线(有时是点)。这是屏幕截图:
虽然这张图片完全没有问题(使用不同的相机角度):
我也尝试过使用 GLES 1 来绘制这些线条并且它起作用了(没有闪烁或随机线条)。也许它与着色器代码有关?顶点着色器取自 android gles 示例,非常简单。
更新:经过更多尝试,我发现只有当相机偏航(y 轴旋转)超过 90 度时才会发生这种情况。在 0-90 yaw 范围内,线条显示正常。我究竟做错了什么?我正在使用 android v4.4.2 在 Galaxy Tab S 上运行该程序。
下面是用于重现错误图像的完整代码:
主要 Activity :
package com.mycompany.bug_test;
import android.opengl.GLSurfaceView;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
public class OpenGLES20Activity extends ActionBarActivity {
private GLSurfaceView mGLView = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if ( mGLView == null ) {
mGLView = new MyGLSurfaceView(this);
}
setContentView(mGLView);
}
}
表面 View :
package com.mycompany.bug_test;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.view.MotionEvent;
class MyGLSurfaceView extends GLSurfaceView {
private final MyGLRenderer mRenderer;
public MyGLSurfaceView(Context context) {
super(context);
setEGLContextClientVersion(2);
mRenderer = new MyGLRenderer();
setRenderer(mRenderer);
}
private final float TOUCH_SCALE_FACTOR = 360.0f;
private float mPreviousX;
private float mPreviousY;
@Override
public boolean onTouchEvent(MotionEvent e) {
float x = e.getX();
float y = e.getY();
int action_type = e.getAction();
if ( action_type == MotionEvent.ACTION_MOVE ) {
float dx = x - mPreviousX;
float dy = y - mPreviousY;
final float div_mag = 10;
float min_dx = dx;
if ( min_dx > (getRootView().getWidth()/div_mag) ) {min_dx = (getRootView().getWidth()/div_mag);}
if ( min_dx < -(getRootView().getWidth()/div_mag) ) {min_dx = -(getRootView().getWidth()/div_mag);}
float min_dy = dy;
if ( min_dy > (getRootView().getHeight()/div_mag) ) {min_dy = (getRootView().getHeight()/div_mag);}
if ( min_dy < -(getRootView().getHeight()/div_mag) ) {min_dy = -(getRootView().getHeight()/div_mag);}
float new_yaw = ( mRenderer.cam_yaw - (min_dx * TOUCH_SCALE_FACTOR / getRootView().getWidth()) ) % 360;
float new_pitch = mRenderer.cam_pitch + (min_dy * TOUCH_SCALE_FACTOR / getRootView().getHeight());
if ( new_pitch > 89 ) {
new_pitch = 89;
}
if ( new_pitch < -89 ) {
new_pitch = -89;
}
synchronized (mRenderer.CAM_LOCK) {
mRenderer.cam_yaw = new_yaw;
mRenderer.cam_pitch = new_pitch;
}
System.out.println("Yaw=" + new_yaw + " Pitch=" + new_pitch);
}
mPreviousX = x;
mPreviousY = y;
return true;
}
}
还有最重要的部分,GL渲染器:
package com.mycompany.bug_test;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
public class MyGLRenderer implements GLSurfaceView.Renderer {
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
" gl_Position = uMVPMatrix * vPosition;" +
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
private int mProgram;
private int mMVPMatrixHandle;
private int mPositionHandle;
private int mColorHandle;
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
float viewAspect;
float fovy = 45;
float fovx = 45;
final Object CAM_LOCK = new Object();
float cam_pos_x = 0;
float cam_pos_y = 0;
float cam_pos_z = 0;
float fcs_pos_x = 0;
float fcs_pos_y = 0;
float fcs_pos_z = 0;
//Try Yaw=246.22672 Pitch=21.992342 with cam_focus_range = 175 to get visible error.
float cam_pitch = 21.992342f;
float cam_yaw = 246.22672f;
float cam_focus_range = 175;
final float line_gap = 100;
final float line_length = 6000;
private final int COORDS_PER_VERTEX = 3;
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
private FloatBuffer vertexBuffer;
private int vertexCount = 0;
public MyGLRenderer() {
float[] GMrkLines = new float[(int)( (line_length / line_gap) + 1 ) * 2 * 2 * COORDS_PER_VERTEX ];
int __P = 0;
for (int ln=0; ln<( (line_length / line_gap) + 1 ); ln++) {
GMrkLines[__P++] = (float)(line_length /2); //x
GMrkLines[__P++] = 0; //y
GMrkLines[__P++] = (float)(line_gap *ln - line_length /2); //z
vertexCount++;
GMrkLines[__P++] = (float)(-line_length /2); //x
GMrkLines[__P++] = 0; //y
GMrkLines[__P++] = (float)(line_gap *ln - line_length /2); //z
vertexCount++;
GMrkLines[__P++] = (float)(line_gap *ln - line_length /2); //x
GMrkLines[__P++] = 0; //y
GMrkLines[__P++] = (float)(line_length /2); //z
vertexCount++;
GMrkLines[__P++] = (float)(line_gap *ln - line_length /2); //x
GMrkLines[__P++] = 0; //y
GMrkLines[__P++] = (float)(-line_length /2); //z
vertexCount++;
}
System.out.println("Vertex count=" + vertexCount);
{
ByteBuffer bb = ByteBuffer.allocateDirect(GMrkLines.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(GMrkLines);
vertexBuffer.position(0);
}
}
@Override
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
mProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(mProgram, vertexShader);
GLES20.glAttachShader(mProgram, fragmentShader);
GLES20.glLinkProgram(mProgram);
GLES20.glUseProgram(mProgram);
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
GLES20.glUniform4fv(mColorHandle, 1, new float[]{0.3f, 0.3f, 0.3f, 1}, 0);
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
GLES20.glEnable( GLES20.GL_DEPTH_TEST );
GLES20.glDepthFunc( GLES20.GL_LEQUAL );
GLES20.glLineWidth(4);
}
@Override
public void onDrawFrame(GL10 unused) {
float _cam_pos_x;
float _cam_pos_y;
float _cam_pos_z;
float _fcs_pos_x;
float _fcs_pos_y;
float _fcs_pos_z;
float _cam_pitch;
float _cam_yaw;
synchronized (CAM_LOCK) {
_cam_pos_x = cam_pos_x;
_cam_pos_y = cam_pos_y;
_cam_pos_z = cam_pos_z;
_fcs_pos_x = fcs_pos_x;
_fcs_pos_y = fcs_pos_y;
_fcs_pos_z = fcs_pos_z;
_cam_pitch = cam_pitch;
_cam_yaw = cam_yaw;
}
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
_fcs_pos_x = 0;
_fcs_pos_y = 0;
_fcs_pos_z = 0;
_cam_pos_y = (float) ( _fcs_pos_y + (cam_focus_range * Math.sin( Math.toRadians(_cam_pitch) )));
double cam_to_focus_horz = cam_focus_range * Math.cos( Math.toRadians(_cam_pitch) );
_cam_pos_x = (float) ( _fcs_pos_x + (cam_to_focus_horz * Math.cos( Math.toRadians(_cam_yaw) )));
_cam_pos_z = (float) ( _fcs_pos_z + (cam_to_focus_horz * Math.sin( Math.toRadians(_cam_yaw) )));
Matrix.setLookAtM(mViewMatrix, 0, _cam_pos_x, _cam_pos_y,_cam_pos_z, _fcs_pos_x, _fcs_pos_y, _fcs_pos_z, 0, 1, 0);
{
float[] mMVPMatrix = new float[16];
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
GLES20.glDrawArrays(GLES20.GL_LINES, 0, vertexCount);
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}
@Override
public void onSurfaceChanged(GL10 unused, int width, int height) {
if (height <= 0) { // avoid a divide by zero error!
height = 1;
}
viewAspect = (float) width / (float) height;
fovx = fovy * viewAspect;
GLES20.glViewport(0, 0, width, height);
GLU_perspective(mProjectionMatrix, 0, fovy, viewAspect, 1.0f, 8000.0f);
}
public static int loadShader(int type, String shaderCode) {
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
int[] _param = new int[4];
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, _param, 0);
System.out.println("Shader no : " + shader);
System.out.println("Compile status = " + _param[0] + " (GL_TRUE=" + GLES20.GL_TRUE + ")");
System.out.println("ERR : " + GLES20.glGetShaderInfoLog(shader));
return shader;
}
void GLU_perspective(float[] RetMtx, int offset, float fovY, float aspect, float zNear, float zFar)
{
float fW, fH;
fH = (float) (Math.tan(fovY / 360 * Math.PI) * zNear);
fW = fH * aspect;
Matrix.frustumM(RetMtx, offset, -fW, fW, -fH, fH, zNear, zFar );
}
}
最佳答案
我遇到了同样的问题,尤其是三星设备(我有 3 台三星设备出现了同样的问题)。事实证明,使用 GL_LINE_STRIP 或 GL_LINES 绘制线条会导致您在屏幕截图中显示的伪影和闪烁。但前提是直线穿过相机平面,并且直线的第一个坐标在相机平面后面,第二个坐标在相机平面前面。反过来 - 没问题。
在我看来,这根本没有意义,因此似乎是驱动程序问题 - 您的代码中没有错误。
作为解决方法,我让顶点着色器检测这个星座,然后翻转顶点。检测是通过检查矩阵的 z 缩放分量 [2][2] 的符号来完成的。在我的例子中,顶点是 {0,0,1} 和 {0,0,-1} - 因此可以通过取反顶点值轻松完成翻转。
// Vertex shader snippet
cPosition = vPosition;
voMatrix = viewMatrix * objMatrix;
if ( voMatrix [2][2] < 0.0 ) cPosition = -vPosition;
我希望这会有所帮助(即使答案来得很晚)。
关于Android GLES 2画线闪烁和奇怪的效果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29091110/
我可以使用 javascript 和其他所有东西,但在重新发明轮子之前,我想知道是否已经有一个类似的 jquery 插件,因为我想使用那个框架而不是 mootools。 我没有钱的问题,特别是 5 欧
我正在 React 应用程序中处理动画。我需要动画在悬停 后开始工作。我尝试了 :hover:after css 但不起作用。将鼠标悬停在图像上后动画可以工作,但我需要在悬停后开始。将鼠标悬停在图像上
我正在使用 jQuery 在按钮单击时实现 slider 效果。我的代码是: $(document).ready(function() { $("#mybutton").click(functio
我需要一个div标签在屏幕右侧滑出,如何使用jQuery获得这种效果?我一直在看这里:http://api.jquery.com/category/effects/sliding/而且这似乎不是我要找
我正在使用此代码实现页面 curl 效果......它在模拟器和设备中工作正常......但它不是(setType:@“pageCurl”)苹果记录的api,这导致它被iPhone拒绝App Stor
我见过各种关于 WPF 效果的引用,但它们似乎是针对位图的,而不是针对文本的。是否可以将除模糊或投影以外的效果应用于XAML中的TextBlock对象? 我想要做的示例可能是轮廓笔划,或斜角/浮雕效果
我见过各种关于 WPF 效果的引用,但它们似乎是针对位图的,而不是针对文本的。是否可以将除模糊或投影以外的效果应用于XAML中的TextBlock对象? 我想要做的示例可能是轮廓笔划,或斜角/浮雕效果
我正在尝试模拟这种效果:http://meyerweb.com/eric/css/edge/complexspiral/demo.html在我的博客上:http://segment6.blogspot
我尝试将样式应用到 Accordion Pane ,但遇到了问题。 这行不通。 accordion.setEffect(new DropShadow(BlurType.ONE_PASS_BOX, Co
关于 Datatables website 的教程足够清楚了: 在我告诉 Datatables 我正在谈论哪一列后,我只需将切换按钮放入: column.visible( ! column.visib
我正在寻找 scratchOut 效果,随便叫它什么。 这是从前景中删除图像的效果,因此背景图像变得可见。 我曾尝试使用 jquery 插件重新创建此效果,但它并不像我希望的那样流畅。 有没有人有这种
本文实例讲述了android实现文字和图片混排(文字环绕图片)效果。分享给大家供大家参考,具体如下: 在平时我们做项目中,或许有要对一张图片或者某一个东西进行文字和图片说明,这时候要求排版美观,所
本文实例讲述了Javafx简单实现【我的电脑资源管理器】效果。分享给大家供大家参考。具体如下: 1. java代码: ?
我是 ngrx 的新手,正在尝试让我的 ngrx 商店的 @Effect 函数正常工作。下面的代码显示了如果我没有使用 ngrx 商店,服务是如何工作的。我首先调用 http.get 来获取列表,然后
基本上我搜索了很多,解决方案建议应用一些 PNG 掩码或不提供所需的解决方案。 我发现了什么。 ffmpeg -i main.mkv -i facecloseup.mkv -filter_compl
有关使用从商店中选择的状态的效果的 Ngrx 文档状态(没有双关语意) Note: For performance reasons, use a flattening operator like co
我有一个数据网格控件,我在其中使用名为 FastShadow 的自定义效果,它就像一个光晕。 我希望效果在其边界之外发光,这样很好,但是当我在顶部绘制另一个形状时,我不希望这个形状受到影响。在本例中,
除了子 div.exception 中的所有内容,我想将 div.main 中的所有文本设为灰色。 div.exception 应该看起来好像类 main 从未添加到父 div。 这可能吗?如果是这样
我有一个 PDF 文件,我想重现此包页面中的页面 curl 效果: https://pub.flutter-io.cn/packages/page_turn 我试过用这个 page_turn插件,它需
我想测试一个效果如下: 如果调度了 LoadEntriesSucces 操作,则效果开始 等待 5 秒 5 秒后发送 http 请求 当响应到达时,将分派(dispatch)新的操作(取决于响应是成功
我是一名优秀的程序员,十分优秀!