Войти
AndroidФорумОбщее

OpenGL + текстуры не отображаются.

#0
19:37, 18 мар. 2013

Скажу сразу навичок я в разработке под андройд ...
вобщем по урокам создал приложение которое производит инициализацию OpenGL + выставляет камеру + загружает текстуры => и все это дело рендерит.
тоесть тут еще нет никаких источников света , темболее шейдеров и так далее...

вообщем проблема в том, все это работает и отображается на эмуляторе...
НО на телефонах нет текстур (( просто белые треугольники !

подскажите куда смотреть?? как подправить?
сразу скажу, что ставил и GL_MODULATE и GL_REPLACE .


#1
19:43, 18 мар. 2013


vitas212
> тоесть тут еще нет никаких источников света , темболее шейдеров
Какую версию OpenGL ES ты используешь? если 1.0 или 1.1 то шейдеры не нужны (их тупо нету в данных реализаций)
Если ты используешь выше версии, то шейдеры нужны 100% т.к. без них ты вообще ни чего не увидишь.

> ообщем проблема в том, все это работает и отображается на эмуляторе...
Но вот почему на эмуляторе всё робит, хз ( возможно там стоят элементарные типовые шейдеры)

#2
19:44, 18 мар. 2013

текстуры не pot?

#3
19:48, 18 мар. 2013

[Deadly]
> Но вот почему на эмуляторе всё робит
Не так давно была проблема, делал несложный шейдер, на эмуляторе проверяю, работает отлично. Закидываю на планшет, результата ноль. Немного поискав причину (часа 2-3) понял ошибку - выставил не верную точность для флоат чисел. Поправил - все заработало везде одинаково.

К ТС - покажи код загрузки и биндинга текстуры.

#4
19:58, 18 мар. 2013

использую 1.0 

gl.glPixelStorei(GL10.GL_UNPACK_ALIGNMENT,1);
        gl.glGenTextures(10, namesTex, 0);
NomTex=0;
    gl.glBindTexture(GL10.GL_TEXTURE_2D, namesTex[NomTex]);
    
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, //указывает, что используется двумерная текстура
            GL10.GL_TEXTURE_MIN_FILTER, // указывает, что установка действует при уменьшении
            GL10.GL_LINEAR_MIPMAP_LINEAR); //установленное правило фильтрации
    gl.glTexParameterf(GL10.GL_TEXTURE_2D,
           GL10.GL_TEXTURE_MAG_FILTER,
           GL10.GL_LINEAR);
    gl.glTexParameterx(GL10.GL_TEXTURE_2D,
           GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT); // для координаты S
      gl.glTexParameterx(GL10.GL_TEXTURE_2D,
           GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT); // для координаты T
    Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),R.drawable.e2_01);
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);  
    bitmap.recycle();

#5
20:21, 18 мар. 2013

vitas212
В данном коде всё норм...
Надеюсь ты ранее инициализировал вот это

// Включим работу с 2D текстурами 
gl.glEnable(GL10.GL_TEXTURE_2D);
// Способ взаимодеиствия текстуры с материалом                                      
gl10.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_MODULATE);

Для того, чтобы определить, как текстура будет взаимодействовать с материалом, из которого сделан объект, используются команды

    void glTexEnv[i f](GLenum target, GLenum pname, GLtype param)
    void glTexEnv[i f]v(GLenum target, GLenum pname, GLtype *params)

Параметр target должен быть равен GL_TEXTURE_ENV, а в качестве pname рассмотрим только одно значение GL_TEXTURE_ENV_MODE, которое наиболее часто применяется. Параметр если param может быть равен:

    GL_MODULATE конечный цвет находится как произведение цвета точки на поверхности и цвета соответствующей ей точки на текстуре.

    GL_REPLACE в качестве конечного цвета используется цвет точки на текстуре.

    GL_BLEND конечный цвет находится как сумма цвета точки на поверхности и цвета соответствующей ей точки на текстуре с учетом их яркости.

#6
20:59, 18 мар. 2013

Размер текстуры 2^N?

#7
21:12, 18 мар. 2013

да работа с тестурами разрешена и все три режима смешивания пробовал.
и кратно 2 размер (128*128)

#8
6:07, 19 мар. 2013

Выручайте! Уже что только не пробовал ((
Может код целиком показать? (Тут проект http://file.qip.ru/arch/L5SLT3BL/openglmini.html )
Или так код. Всего три класса:
файл MainActivity.java

package com.example.openglmini;

import android.os.Bundle;
import android.app.Activity;
import android.view.MotionEvent;
import android.view.Window;
import android.view.WindowManager;

public class MainActivity extends Activity {
    // создадим ссылку на экземпляр нашего класса MyClassSurfaceView
    private MyClassSurfaceView mGLSurfaceView;
    
    // переопределим метод onCreate
    @Override
    public void onCreate(Bundle savedInstanceState){
                super.onCreate(savedInstanceState);
                // запрос на отключение строки заголовка 
                requestWindowFeature(Window.FEATURE_NO_TITLE);
                // перевод приложения в полноэкранный режим
                getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
                //создадим экземпляр нашего класса MyClassSurfaceView
                 mGLSurfaceView = new MyClassSurfaceView(this);
                //вместо вызова стандартного контента  
                //setContentView(R.layout.main);
                //вызовем экземпляр нашего класса MyClassSurfaceView  
                setContentView(mGLSurfaceView);
                // на экране появится поверхность для рисования в OpenGL ES
    }

    @Override
    protected void onPause() {
                super.onPause();
                mGLSurfaceView.onPause();
    }

    @Override
    protected void onResume() {
                super.onResume();
                mGLSurfaceView.onResume();
    }
}
файл MyClassSurfaceView.java
package com.example.openglmini;

import android.content.Context;
import android.opengl.GLSurfaceView;

public class MyClassSurfaceView extends GLSurfaceView{
    //создадим ссылку для хранения экземпляра нашего класса рендерера
    private MyClassRenderer renderer;    
    // конструктор
    public MyClassSurfaceView(Context context) {
                // вызовем конструктор родительского класса GLSurfaceView
                super(context);
                // создадим экземпляр нашего класса MyClassRenderer
                //renderer = new MyClassRenderer(context);
                renderer = new MyClassRenderer();
                renderer.context=context;                
                // запускаем наш экземпляр рендерера 
                setRenderer(renderer);  
                // установим режим циклического запуска метода onDrawFrame
                // в рендерере
                setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);              
                
    } 
}
файл MyClassRenderer.java
package com.example.openglmini;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.opengl.GLUtils;


public class MyClassRenderer implements GLSurfaceView.Renderer{
  public Context context;
  public int[] namesTex=new int[1];

  public void Start2dDraw(GL10 gl)
  {
        gl.glMatrixMode(GL10.GL_PROJECTION);  // Change Matrix Mode to Projection
        gl.glLoadIdentity();             // Reset View
        gl.glOrthof(0, 320, 0, 480, 0, 100);      
        gl.glMatrixMode(GL10.GL_MODELVIEW);   // Change Projection to Matrix Mode
        gl.glLoadIdentity();
        gl.glTranslatef(0, 0, -1);    
  }

  @Override
  public void onDrawFrame(GL10 gl) {
        // очищаем буферы глубины и цвета
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        // перейдем в режим работы с матрицей модели-вида
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        // сбросим матрицу модели-вида на единичную
        gl.glLoadIdentity();
        // далее выполним расчет кадра и его рисование.......  
        gl.glTranslatef(0, 0, 0.0f);
        
        Start2dDraw(gl);  

        FloatBuffer vertexBuffer;
        ByteBuffer bb = ByteBuffer.allocateDirect(48);
        bb.order(ByteOrder.nativeOrder());
        vertexBuffer = bb.asFloatBuffer();  
        
        float [] trianglecoord={0,128,0,  0,0,0,  128,128,0,  128,0,0};
        vertexBuffer.position(0);
        vertexBuffer.put(trianglecoord);
        vertexBuffer.position(0);
        //***
        
        FloatBuffer texcoordBuffer;
        ByteBuffer bb1 = ByteBuffer.allocateDirect(32);
        bb1.order(ByteOrder.nativeOrder());
        texcoordBuffer = bb1.asFloatBuffer(); 
        
        float [] texcoordBufferArray={0.0f,1.0f, 0.0f,0.0f, 1.0f,1.0f, 1.0f,0.0f};
        texcoordBuffer.position(0); 
        texcoordBuffer.put(texcoordBufferArray);
        texcoordBuffer.position(0); 
  
        gl.glEnable(GL10.GL_TEXTURE_2D);
        gl.glBindTexture(GL10.GL_TEXTURE_2D, namesTex[0]);
        
       
          //gl.glTexEnvx(GL10.GL_TEXTURE_ENV,GL10.GL_TEXTURE_ENV_MODE,GL10.GL_REPLACE ); 
          // Способ взаимодеиствия текстуры с материалом                                      
          gl.glTexEnvf(GL10.GL_TEXTURE_ENV,GL10.GL_TEXTURE_ENV_MODE,GL10.GL_MODULATE);
        
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
        
        gl.glTexCoordPointer(2,GL10.GL_FLOAT,0,texcoordBuffer);
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);       
  }

  @Override
  public void onSurfaceChanged(GL10 gl, int width, int height) {
        // установим область просмотра равной размеру экрана
        gl.glViewport(0, 0, width, height);
        // подсчитаем отношение ширина/высота
        float ratio = (float) width / height;
        // перейдем в режим работы с матрицей проекции
        gl.glMatrixMode(GL10.GL_PROJECTION);
        // сбросим матрицу проекции на единичную
        gl.glLoadIdentity();
        // устанавливаем перспективную проекцию
        // угол обзора 60 градусов
        // передняя отсекающая плоскость 0.1
        // задняя отсекающая плоскость 100
        GLU.gluPerspective (gl, 60, ratio, 0.1f, 100f);
        // перейдем в режим работы с матрицей модели-вида
        gl.glMatrixMode(GL10.GL_MODELVIEW); 
  }
  @Override
  public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        // включим пересчет нормалей на единичную длину
        gl.glEnable(GL10.GL_NORMALIZE);
        // включим сглаживание цветов
        gl.glShadeModel(GL10.GL_SMOOTH);
        // включим проверку глубины
        gl.glEnable(GL10.GL_DEPTH_TEST);
        gl.glDepthFunc(GL10.GL_LEQUAL);
        
    // далее загружаем текстуры .................. 
        
        
        gl.glPixelStorei(GL10.GL_UNPACK_ALIGNMENT,1);
        gl.glGenTextures(1, namesTex, 0);
        gl.glBindTexture(GL10.GL_TEXTURE_2D, namesTex[0]);
        
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, //указывает, что используется двумерная текстура
                GL10.GL_TEXTURE_MIN_FILTER, // указывает, что установка действует при уменьшении
                GL10.GL_LINEAR_MIPMAP_LINEAR); //установленное правило фильтрации
        gl.glTexParameterf(GL10.GL_TEXTURE_2D,
               GL10.GL_TEXTURE_MAG_FILTER,
               GL10.GL_LINEAR);
        gl.glTexParameterx(GL10.GL_TEXTURE_2D,
               GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT); // для координаты S
          gl.glTexParameterx(GL10.GL_TEXTURE_2D,
               GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT); // для координаты T
        Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(),R.drawable.eee);
        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);  
        bitmap.recycle();        
        }    
}

#9
7:05, 19 мар. 2013

Попробуй добавить генерацию мипмап уровней, должно быть примерно следующее:
GLUtils.build2DMipmaps(...);

#10
11:30, 19 мар. 2013

vitas212
Я так помню смутно но когда я писал свой фрейм ворк для андроида столкнулся с такой ерундистикой, что при вызове функции OpenGL - glTexCoordPointer.
А именно то что 3 параметр по докам может быть 0, но на деле мне пришлось его указывать (пример ниже). Это кстати относится и к glVertexPointer, glColorPointer.

glTexCoordPointer(2, GL10.GL_FLOAT, 8, m_curTextureBuffer)

Не знаю правда с чем это связанно, но у меня всё робит отлично.

На счёт мипмапов тоже возможен данный глюк для ведроида и они принципиально необходимы ( у меня они включены в работу с текстурами).

Вот для примера моя рабочая версия для ведроида на java

    // -------------------------------------------------------------------------------------------------------------
    // Функции работы с текстурами
    // -------------------------------------------------------------------------------------------------------------

    // Загрузка текстуры из ресурсов (на выходе её индентификационный номер текстуры)
    public int Texture_LoadR(int idPicture, int filter) {
        int texture = 0;
        // Обработка только когда переменная m_gl указывает на интерфейс OpenGL ES 1.0
        if(m_bWorkGL) {
            // Сгенерируем номер текстуры в GPU и настроим её
            texture = _AdjustmentTexture(filter);
            // Загружаем картинку с идентификаторм idPicture - это уникальный номер картинки в R.java
            Bitmap bitmap = BitmapFactory.decodeResource(m_MainActivity.getResources(), idPicture);
            // Передача текстуры в OpenGL ES 1.0
            GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
            // Удалим текстуру из памяти
            bitmap.recycle();
        }
        return texture;
    }

    // Загрузка текстуры из папки Assets (на выходе её индентификационный номер текстуры)
    public int Texture_LoadA(String path_texture, int filter) {
        int texture = 0;
        // Обработка только когда переменная m_gl указывает на интерфейс OpenGL ES 1.0
        if(m_bWorkGL) {
            // Сгенерируем номер текстуры в GPU и настроим её
            texture = _AdjustmentTexture(filter);
            // Откроем поток для нашего файла
            InputStream is = File_OpenAssets(path_texture, system.FILE_ASSETS_STREAMING);
            // Загружаем картинку из потока
            Bitmap bitmap = BitmapFactory.decodeStream(is);
            // Передача текстуры в OpenGL ES 1.0
            GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
            // Удалим текстуру из памяти
            bitmap.recycle();
            // Закроем поток
            try{
                is.close();
            }catch (IOException e) {
                e.getStackTrace();
            }
        }
        return texture;
    }

    // Удаление текстуры по сгенерированому номеру GPU
    public void Texture_Delete(int num_texture) {
        int[] texture  =  new int[1];
        // Заполним массив одним значением (удаляемой текстурой)
        texture[0]  = num_texture;
        // Обработка только когда переменная m_gl указывает на интерфейс OpenGL ES 1.0
        if(m_bWorkGL) {
            m_gl.glDeleteTextures(1, texture, 0);
        }
    }

    // Генерация номера текстуры в GPU и настройка её
    private int _AdjustmentTexture(int filter) {
        int[] texture  =  new int[1];
        // Выравнивание данных по одному байту на каждую состовляющую цвета текстуры
        m_gl.glPixelStorei(GL10.GL_UNPACK_ALIGNMENT, 1);
        // Генерируем массив свободных имён текстур, состоящий из одного элемента
        m_gl.glGenTextures(1, texture, 0);
        // Устанавливаем текстуру с номером texture в качестве текущей активной текстуры
        m_gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[0]);
        // Включаем автоматическую генерацию мипмапов
        m_gl.glTexParameterx(GL11.GL_TEXTURE_2D, GL11.GL_GENERATE_MIPMAP, GL11.GL_TRUE);
        // Выбирим тип фильтрации текстуры
        switch(filter) {
            case system.TWS_MIGMAN_FILTER_POINT:
                // Установим принцип работы при сжатии текстуры
                m_gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
                // Установим принцип работы при растягивании текстуры
                m_gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
                break;

            case system.TWS_MIGMAN_FILTER_MIPMAP:
                // Установим принцип работы при сжатии текстуры
                m_gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR_MIPMAP_LINEAR);
                // Установим принцип работы при растягивании текстуры
                m_gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
                break;

            case system.TWS_MIGMAN_FILTER_NONE:
            default:
                // Установим принцип работы при сжатии текстуры
                m_gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
                // Установим принцип работы при растягивании текстуры
                m_gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);
                break;
        }
        // Определим принцип наложения текстуры
        switch(filter & system.TWS_WRAP_REPEAT) {
            case system.TWS_WRAP_CLAMP:
                m_gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
                m_gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
                break;
            case system.TWS_WRAP_REPEAT:
                m_gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
                m_gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
                break;
        }
        return texture[0];
    }

И к нему константы

    // // Перечисление Texture Work State
    public final static int TWS_MIGMAN_FILTER_NONE    = 0x00000000;    // Отключение фильтрации текстуры
    public final static int TWS_MIGMAN_FILTER_POINT    = 0x00000001;    // Фильтрация осуществляется путём использования ближайших четырёх элементов текстуры
    public final static int TWS_MIGMAN_FILTER_MIPMAP  = 0x00000002;    // Фильтрация осуществляется путём использования мипмапов
    public final static int TWS_WRAP_CLAMP        = 0x00000000;    // Если текстура меньше полигона она
    public final static int TWS_WRAP_REPEAT        = 0x00000004;    // Если текстура меньше полигона она копируется
#11
11:34, 19 мар. 2013

Ну вот тебе для размышления

// -------------------------------------------------------------------------------------------------------------
    // Функции работы с файлами
    // -------------------------------------------------------------------------------------------------------------

    // Открытие файла находящихся в папке Assests
    public InputStream File_OpenAssets(String path_file, int access) {
        InputStream is = null;
        // Получим доступ к менеджеру файлов папки Assets
        int  access_file = AssetManager.ACCESS_UNKNOWN;
        // Проверим были ли раньше получен указатель менеджер активов, если нет то получим его
        if(m_fileAM == null) { m_fileAM = m_MainActivity.getAssets(); }
        // Откроем файл с указанным именем
        try {
            // Переопределим типы доступа к файлу
            switch(access) {
                case system.FILE_ASSETS_BUFFER:    access_file = AssetManager.ACCESS_BUFFER;    break;
                case system.FILE_ASSETS_RANDOM:    access_file = AssetManager.ACCESS_RANDOM;    break;
                case system.FILE_ASSETS_STREAMING:  access_file = AssetManager.ACCESS_STREAMING;  break;
            }
            // Открытие файла с указанными параметрами и получение его потока
            is = m_fileAM.open(path_file, access_file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return is;
    }

    // Закрытие AssetManager
    public void File_CloseAssets() {
        // Проверим были раньше получен указатель менеджер активов, если да то закроем его
        if(m_fileAM != null) { m_fileAM.close(); m_fileAM = null; }
    }
Константы
    // Константы работы с файлами в папке Assets
    public final static int FILE_ASSETS_BUFFER      = 0x00000000;    // Использовать загрузку в буфер
    public final static int FILE_ASSETS_RANDOM      = 0x00000001;    // Возможность чтение кусками (chunk), с возможностью перехода по файлу
    public final static int FILE_ASSETS_STREAMING    = 0x00000002;    // Последовательное чтение, с редким использованием перехода по файлу

А вобще смотри вот этот видос:

И то что я на нём делал:

#12
13:19, 19 мар. 2013

О, нет! оказывается в настройках AVD можно устанавливать галочку "Use Host GPU" и тогда текстуры не отображаются и на эмуляторе ))
ну такой вот я знаток анлройда )) всего четвертый день )) ох тяжко мне после делфи))

ну в общем новости хорошие ))
косяк зарыт тут:

gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR_MIPMAP_LINEAR);// не работает

gl.glTexParameterf(GL10.GL_TEXTURE_2D,GL10.GL_TEXTURE_MIN_FILTER,GL10.GL_LINEAR);// РАБОТАЕТ
устал... столько перепробывал вариантов...  даже не буду щас читать чем по документации они отличаютс))

хочу сказать всем большое спасибо за то, что давали направления где смотреть ))
ну и за то что всетаки помогли найти решение))

#13
14:34, 19 мар. 2013

Мипы надо сгенерировать было. Не знаю, как это делается на es 1.0, но на обычном gl куча способов.

AndroidФорумОбщее

Тема в архиве.