Разработка мобильных приложений. Программирование мобильных устройств на языке Kotlin. Учебное пособие для СПО
.pdf
Элемент Button
Создать кнопки в мобильном приложении на языке Kotlin можно с использованием Android SDK и, в частности, элемента Button.
Самый распространенный способ добавления кнопки – через файл макета (XML). Этот файл определяет визуальную структуру вашего экрана. Обычно макеты расположены в директории res/layout/. Например, activity_main.xml.
<Button android:id="@+id/myButton"
android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Нажми меня!" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent"/>
Разберем атрибуты:
•android:id="@+id/myButton": Уникальный идентификатор кнопки, используется для доступа к кнопке из кода Kotlin. @+id/ означает, что мы создаем новый ID.
•android:layout_width="wrap_content": Ширина кнопки определяется содержимым (текстом).
•android:layout_height="wrap_content": Высота кнопки определяется содержимым (текстом).
•android:text="Нажми меня!": Текст, отображаемый на кнопке.
•app:layout_constraintTop_toTopOf="parent", app:layout_constraintBottom_to BottomOf="parent", app:layout_constraintStart_toStartOf="parent", app:layout _constraintEnd_toEndOf="parent": Атрибуты ConstraintLayout, которые центрируют кнопку на экране. Используйте их или другие атрибуты компоновки, чтобы расположить кнопку в желаемом месте.
Теперь, когда кнопка определена в макете, необходимо добавить код Kotlin, чтобы обрабатывать нажатия на нее. В вашем Activity или Fragment используйте findViewById() для получения ссылки на кнопку. Этот метод принимает ID кнопки в качестве аргумента. Установите слушатель OnClickListener на кнопку. Этот слушатель содержит код, который будет выполнен при нажатии на кнопку.
import androidx.appcompat.app.AppCompatActivity import android.os.Bundle
import android.widget.Button import android.widget.Toast
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
32
31
super.onCreate(savedInstanceState) setContentView(R.layout.activity_main)
val myButton: Button = findViewById(R.id.myButton) myButton.setOnClickListener {
// Код, который выполняется при нажатии на кнопку
Toast.makeText (this, "Кнопка нажата!", Toast.LENGTH_SHORT).show()
}
}
}
Объяснение кода:
•val myButton: Button = findViewById(R.id.myButton): Находит кнопку с
ID myButton(определенным в XML) и присваивает ее
переменной myButton. Обратите внимание на явное указание типа Button.
•myButton.setOnClickListener { ... }: Устанавливает слушатель нажатий на кнопку.
•Toast.makeText(this, "Кнопка нажата!", Toast.LENGTH_SHORT).show():
Внутри слушателя, этот код отображает короткое всплывающее сообщение (Toast) на экране. Вы можете заменить этот код любым другим кодом, который вы хотите выполнить при нажатии кнопки.
Прозрачность фигур
В OpenGL ES 1.0 для реализации прозрачности (полупрозрачности) необходимо использовать смешивание цветов (blending). Смешивание цветов позволяет комбинировать цвет нового фрагмента (пикселя) с цветом, уже находящимся в буфере кадра (framebuffer). В OpenGL ES 1.0 это осуществляется через фиксированный конвейер с использованием функций glEnable() и glBlendFunc().
Ключевые концепции:
•Альфа-канал (Alpha Channel): Альфа-канал определяет уровень непрозрачности цвета. Значение 0.0 означает полную прозрачность, а значение 1.0 – полную непрозрачность. Значения между 0.0 и 1.0 представляют собой полупрозрачность.
•Смешивание цветов (Blending): Процесс комбинирования цвета нового фрагмента с цветом, уже находящимся в буфере кадра. Определяется с помощью функции glBlendFunc().
•Включение смешивания: Смешивание необходимо включить с помощью glEnable(GL10.GL_BLEND).
•Функция смешивания (Blend Function): Определяет, как комбинируются цвета. Задается с помощью glBlendFunc(sfactor, dfactor), где:
33
32
osfactor: Множитель для исходного цвета (source color – цвет нового фрагмента).
odfactor: Множитель для целевого цвета (destination color – цвет, уже находящийся в буфере кадра).
Шаги для реализации прозрачности:
1. Включить смешивание: gl.glEnable(GL10.GL_BLEND)
2. Выбрать функцию смешивания: gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA)
oЭтот наиболее распространенный режим смешивания обеспечивает корректную прозрачность:
▪GL10.GL_SRC_ALPHA: Исходный цвет умножается на его альфа-значение.
▪GL10.GL_ONE_MINUS_SRC_ALPHA: Целевой цвет умножается на (1 – альфа-значение исходного цвета).
▪В результате, чем больше альфа-значение исходного цвета, тем больше он влияет на конечный цвет, и тем меньше влияния оказывает цвет, уже находящийся в буфере кадра.
3.Отключить тест глубины (Depth Test) перед отрисовкой прозрачных объектов:gl.glDisable(GL10.GL_DEPTH_TEST)
oТест глубины сравнивает глубину нового фрагмента с глубиной фрагмента, уже находящегося в буфере глубины. Если новый фрагмент находится дальше, он отбрасывается. Для корректной отрисовки прозрачных объектов необходимо отключить тест глубины, чтобы прозрачные объекты могли быть отрисованы даже поверх объектов, находящихся дальше.
4.Назначить альфа-значения цветам: Установите альфа-канал для цветов вершин или примитивов.
5.Отсортировать объекты по глубине (необязательно, но рекомендуется): Если у вас несколько прозрачных объектов, отрисовывайте их в порядке удаленности от камеры (сначала самые дальние, потом самые ближние). Это поможет избежать артефактов смешивания.
6.Отрисовать фигуры: Отрисуйте ваши фигуры, используя буферы вершин
ицветов, как обычно.
7.Включить тест глубины (Depth Test) после отрисовки прозрачных объектов:gl.glEnable(GL10.GL_DEPTH_TEST)
•Чтобы последующие непрозрачные объекты отображались корректно, необходимо включить тест глубины обратно.
34
33
// Цвет квадрата (красный с альфой 0.5 – полупрозрачный) private val squareColors = floatArrayOf(
1.0f, 0.0f, 0.0f, 0.5f // Top Left 1.0f, 0.0f, 0.0f, 0.5f // Bottom Left 1.0f, 0.0f, 0.0f, 0.5f // Bottom Right 1.0f, 0.0f, 0.0f, 0.5f // Top Right
)
// Включаем смешивание gl.glEnable(GL10.GL_BLEND) gl.glBlendFunc(GL10.GL_SRC_ALPHA,
GL10.GL_ONE_MINUS_SRC_ALPHA)
// Отключаем тест глубины *перед* отрисовкой прозрачного
объекта
gl.glDisable(GL10.GL_DEPTH_TEST)
// Рисуем квадрат gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, 4)
//Включаем тест глубины *после* отрисовки прозрачного объекта gl.glEnable(GL10.GL_DEPTH_TEST)
//Отключаем смешивание (если больше не нужно) gl.glDisable(GL10.GL_BLEND)
}
}
Kotlin
Важные моменты:
•Порядок отрисовки: В OpenGL ES 1.0 (без шейдеров) порядок отрисовки прозрачных объектов критичен. Поскольку тест глубины отключен во время отрисовки прозрачных объектов, они отрисовываются в том порядке, в котором они передаются в конвейер OpenGL. Поэтому рекомендуется отрисовывать прозрачные объекты от дальних к ближним. Это гарантирует, что правильно комбинируются цвета. В сложных сценах ручная сортировка может быть сложной, и результат может быть не идеальным.
•Тест глубины: Обязательно включите тест глубины обратно после отрисовки прозрачных объектов, чтобы избежать проблем с отрисовкой непрозрачных объектов.
•Цвета: Убедитесь, что вы правильно задаете альфа-значения для цветов.
35
34
• Функции смешивания: Существуют и другие функции смешивания,
но GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA
является наиболее распространенной и часто используемой.
•Производительность: Прозрачность может снизить производительность, особенно если используется много прозрачных объектов. По возможности старайтесь минимизировать использование прозрачности.
•Другие функции смешивания:
oGL10.GL_ONE, GL10.GL_ZERO: Полностью заменяет целевой цвет исходным. Используется для копирования текстур.
oGL10.GL_SRC_COLOR, GL10.GL_DST_COLOR: Умножает исходный или целевой цвет на его компоненты.
oGL10.GL_ONE, GL10.GL_ONE: Аддитивное смешивание
(складывает цвета). Используется для эффектов свечения.
oGL10.GL_DST_COLOR, GL10.GL_ZERO: Умножает целевой цвет на исходный.
ПРАКТИЧЕСКАЯ РАБОТА 4
Добавьте 3 кнопки на сцену (влево, вправо, информация). Выбор планеты указывается при помощи куба, в который вписана планета (куб частично прозрачен, внутри него планета).
36
35
Модель Фонга. Ч. 1
Модель освещения Фонга (Phong Lighting Model) – это эмпирическая модель освещения, используемая в компьютерной графике для имитации отражения света от поверхности объекта. Она состоит из трех компонентов: рассеянного (diffuse), зеркального (specular) и окружающего (ambient) освещения. В OpenGL ES 1.0, из-за фиксированного конвейера, модель Фонга реализуется с использованием встроенных возможностей освещения OpenGL.
Теоретические основы модели Фонга: 1. Рассеянное освещение (Diffuse Lighting):
o Представляет собой свет, который равномерно рассеивается от поверхности во всех направлениях.
o Зависит от угла между вектором нормали к поверхности (N) и вектором направления света (L).
o Интенсивность рассеянного света максимальна, когда N и L коллинеарны (угол равен 0) и уменьшается по мере увеличения угла между ними.
oФормула: Diffuse = LightColor * MaterialDiffuse * max(0, N · L)
▪LightColor: Цвет источника света.
▪MaterialDiffuse: Цвет рассеянного отражения материала.
▪N · L: Скалярное произведение векторов N и L. max(0, N · L) гарантирует, что интенсивность не будет отрицательной, когда свет находится с обратной стороны поверхности.
2.Зеркальное освещение (Specular Lighting):
oПредставляет собой блик или отражение света от глянцевой поверхности.
oЗависит от угла между вектором отражения света (R) и вектором направления на камеру (V).
o Интенсивность зеркального света максимальна, когда R и V коллинеарны, и быстро уменьшается по мере увеличения угла между ними.
oФормула: Specular = LightColor * MaterialSpecular * max(0, (V ·
R)^Shininess)
▪LightColor: Цвет источника света.
▪MaterialSpecular: Цвет зеркального отражения материала.
▪V · R: Скалярное произведение векторов V и R.
▪Shininess: Коэффициент глянца материала, определяющий размер и яркость блика. Чем больше Shininess, тем меньше и ярче блик.
3.Окружающее освещение (Ambient Lighting):
oПредставляет собой рассеянный свет, который присутствует в окружающей среде и равномерно освещает все поверхности.
o Не зависит от положения источника света или угла между поверхностью и источником света.
37
36
o Обычно используется для имитации непрямого освещения и заполнения теней.
oФормула: Ambient = LightColor * MaterialAmbient
▪LightColor: Цвет источника света.
▪MaterialAmbient: Цвет окружающего отражения материала.
4.Итоговое освещение:
oИтоговый цвет поверхности вычисляется как сумма трех
компонентов:
o FinalColor = Ambient + Diffuse + Specular
Реализация модели Фонга в OpenGL ES 1.0 (Kotlin):
OpenGL ES 1.0 предоставляет встроенные функции для работы с освещением. Необходимо настроить параметры освещения, источники света и свойства материалов.
override fun onSurfaceCreated(gl: GL10, config: EGLConfig) { gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f) gl.glEnable(GL10.GL_DEPTH_TEST)
//1. Включение освещения gl.glEnable(GL10.GL_LIGHTING)
//2. Настройка источника света
val lightAmbient = floatArrayOf(0.2f, 0.2f, 0.2f, 1.0f) // Ambient light val lightDiffuse = floatArrayOf(0.8f, 0.8f, 0.8f, 1.0f) // Diffuse light val lightSpecular = floatArrayOf(0.5f, 0.5f, 0.5f, 1.0f) // Specular light val lightPosition = floatArrayOf(0.0f, 3.0f, 3.0f, 1.0f) // Light position
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, lightAmbient,
0)
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, lightDiffuse, 0) gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, lightSpecular,
0)
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightPosition,
0)
gl.glEnable(GL10.GL_LIGHT0) // Enable LIGHT0
// 3. Настройка материала
val materialAmbient = floatArrayOf(0.2f, 0.2f, 0.2f, 1.0f) // Ambient
material
val materialDiffuse = floatArrayOf(0.8f, 0.8f, 0.8f, 1.0f) // Diffuse
material
val materialSpecular = floatArrayOf(0.8f, 0.8f, 0.8f, 1.0f) // Specular
material
val materialShininess = 32.0f // Shininess
38
37
gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, materialAmbient, 0)
gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, materialDiffuse, 0)
gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_SPECULAR, materialSpecular, 0)
gl.glMaterialf(GL10.GL_FRONT_AND_BACK, GL10.GL_SHININESS, materialShininess)
//4. Включение нормалей gl.glEnableClientState(GL10.GL_NORMAL_ARRAY)
//Enable vertex and color state gl.glEnableClientState(GL10.GL_VERTEX_ARRAY)
//Point to buffers
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer) gl.glNormalPointer(GL10.GL_FLOAT, 0, normalBuffer)
}
Разъяснение кода:
1.Включение освещения: gl.glEnable(GL10.GL_LIGHTING) включает общую систему освещения OpenGL.
2.Настройка источника света (LIGHT0):
ogl.glLightfv(): Используется для установки свойств источника света
(ambient, diffuse, specular, position).
oGL10.GL_LIGHT0: Идентификатор источника света (можно использовать несколько источников света).
olightAmbient, lightDiffuse, lightSpecular: Массивы, содержащие значения цвета для каждого компонента освещения.
olightPosition: Массив, содержащий координаты положения источника света. Важно помнить, что это положение в системе координат мира.
ogl.glEnable(GL10.GL_LIGHT0): Включает конкретный источник света (LIGHT0).
3.Настройка материала:
ogl.glMaterialfv(): Используется для установки свойств материала
(ambient, diffuse, specular).
oGL10.GL_FRONT_AND_BACK: Указывает, что свойства применяются к обеим сторонам поверхности.
omaterialAmbient, materialDiffuse, materialSpecular: Массивы,
содержащие значения цвета для каждого компонента отражения материала.
ogl.glMaterialf(): Используется для установки коэффициента глянца
(shininess).
39
38
oGL10.GL_SHININESS: Определяет степень глянцевости поверхности.
4.Включение нормалей:
ogl.glEnableClientState(GL10.GL_NORMAL_ARRAY): Включает использование массива нормалей.
ogl.glNormalPointer(GL10.GL_FLOAT, 0, normalBuffer): Указывает
OpenGL на буфер, содержащий нормали.
5.Нормали:
ocubeNormals: Массив, содержащий нормали для каждой вершины куба. Нормаль – это вектор, перпендикулярный поверхности в данной вершине. Он используется для расчета освещения. Важно, чтобы нормали были нормализованы (имели единичную длину).
6.Матрицы: Важно помнить, что преобразования (матрицы) применяются до расчета освещения. Убедитесь, что ваши нормали правильно трансформированы вместе с вашими вершинами. Хотя в OpenGL ES 1.0 нет прямой поддержки для преобразования нормалей, обычно достаточно просто перемножить нормали на матрицу моделирования (Model Matrix).
Важные замечания:
•Нормализация нормалей: Важно убедиться, что нормали нормализованы (имеют единичную длину). В OpenGL ES 1.0 можно использовать glEnable(GL10.GL_NORMALIZE) для автоматической нормализации нормалей.
•Положение источника света: Положение источника света влияет на освещение объекта. Попробуйте изменить положение источника света, чтобы увидеть, как это влияет на результат.
•Цвета и коэффициенты: Изменение цветов и коэффициентов освещения и материала может сильно повлиять на внешний вид объекта.
•Производительность: Освещение может снизить производительность, особенно если используется несколько источников света.
Альтернативные подходы (ограничены в ES 1.0):
•Использование текстур: Можно использовать текстуры для имитации более сложных эффектов освещения, таких как карты нормалей или карты отражения. Однако это требует написания более сложного кода и может снизить производительность.
•Запеченное освещение (Baked Lighting): Можно предварительно рассчитать освещение и сохранить его в текстурах или массивах вершин. Этот подход может улучшить производительность, но он не позволяет изменять освещение в реальном времени.
40
39
Open GL ES 2.0.
OpenGL ES 2.0 (OpenGL for Embedded Systems 2.0) представляет собой значительный шаг вперед по сравнению с OpenGL ES 1.x,
предоставляя программируемый графический конвейер. Это означает, что разработчики получают полный контроль над процессом рендеринга, используя шейдеры – небольшие программы, выполняемые на GPU. Это открывает двери для гораздо более сложных и реалистичных графических эффектов, а также для оптимизации рендеринга под конкретные устройства.
Ключевые отличия от OpenGL ES 1.x:
•Программируемый конвейер: Вместо фиксированного конвейера OpenGL ES 1.x, OpenGL ES 2.0 использует программируемые шейдеры. Это дает разработчикам гораздо больше контроля над тем, как отображаются объекты.
•Шейдеры: Шейдеры – это небольшие программы, написанные на GLSL ES (OpenGL Shading Language for Embedded Systems), которые выполняются на GPU. Есть два основных типа шейдеров:
o Вершинные шейдеры (Vertex Shaders): Отвечают за преобразование координат вершин и передачу данных во фрагментный шейдер.
o Фрагментные шейдеры (Fragment Shaders): Отвечают за
определение цвета каждого фрагмента (пикселя) на экране. |
|
|
• Отсутствие |
фиксированной функциональности: OpenGL |
ES |
2.0 не имеет |
фиксированных функций освещения, текстурирования |
и |
преобразования, которые были в OpenGL ES 1.x. Все это должно быть реализовано с помощью шейдеров.
•Совместимость: OpenGL ES 2.0 не обратно совместим с OpenGL ES 1.x. Это означает, что приложения, написанные для OpenGL ES 1.x, не будут работать без изменений на устройствах, поддерживающих только OpenGL
ES 2.0.
•Улучшенная производительность (потенциально): Хотя программирование становится сложнее, правильно написанные шейдеры
могут обеспечить лучшую производительность, поскольку они позволяют оптимизировать процесс рендеринга под конкретное оборудование.
Основные понятия OpenGL ES 2.0:
1.GLSL ES (OpenGL Shading Language for Embedded Systems): Язык программирования, используемый для написания шейдеров. GLSL ES имеет C-подобный синтаксис.
2.Атрибуты (Attributes): Переменные, которые передаются в вершинный шейдер для каждой вершины. Обычно используются для хранения информации о положении вершин, нормалях, текстурных координатах и цветах.
3.Uniform-переменные (Uniforms): Переменные, которые передаются в шейдеры из приложения и остаются постоянными для всего примитива
41
40
